﻿
HmJS.register('core.core', function ($ns) {

	// #region -- core --

	// #region - MooTools -

	/*
	---
	MooTools: the javascript framework

	web build:
	- http://mootools.net/core/7c56cfef9dddcf170a5d68e3fb61cfd7

	packager build:
	- packager build Core/Core Core/Array Core/String Core/Number Core/Function Core/Object Core/Event Core/Browser Core/Class Core/Class.Extras Core/Slick.Parser Core/Slick.Finder Core/Element Core/Element.Style Core/Element.Event Core/Element.Dimensions Core/Fx Core/Fx.CSS Core/Fx.Tween Core/Fx.Morph Core/Fx.Transitions Core/Request Core/Request.HTML Core/Request.JSON Core/Cookie Core/JSON Core/DOMReady Core/Swiff

	/*
	---

	name: Core

	description: The heart of MooTools.

	license: MIT-style license.

	copyright: Copyright (c) 2006-2010 [Valerio Proietti](http://mad4milk.net/).

	authors: The MooTools production team (http://mootools.net/developers/)

	inspiration:
	- Class implementation inspired by [Base.js](http://dean.edwards.name/weblog/2006/03/base/) Copyright (c) 2006 Dean Edwards, [GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)
	- Some functionality inspired by [Prototype.js](http://prototypejs.org) Copyright (c) 2005-2007 Sam Stephenson, [MIT License](http://opensource.org/licenses/mit-license.php)

	provides: [Core, MooTools, Type, typeOf, instanceOf, Native]

	...
	*/

	this.MooTools = {
		version: '1.4.2dev',
		build: '63659d25058b1139ada58c34373a7ccb1dde2d1b'
	};

	// #endregion

	// 将Type的定义放入了闭包之中，由于此匿名函数在全局环境中，所以this指的也就是window。

	// #region - typeOf,instanceOf -

	// 检测传入参数的类型
	//
	// Syntax: typeOf(obj);
	//
	// Arguments: 
	//	item - 目标检测对象
	//
	// Returns: 
	//	'element' - (string) DOM元素节点
	//	'textnode' - (string) DOM文本节点
	//	'whitespace' - (string) DOM空白节点
	//	'arguments' - (string) arguments 对象 
	//	'array' - (string) 数组
	//	'object' - (string) Object对象
	//	'string' - (string) 字符串
	//	'number' - (string) 数字
	//	'date' - (string) 日期对象
	//	'boolean' - (string) 布尔值
	//	'function' - (string) 函数对象
	//	'regexp' - (string) 正则表达式对象
	//	'class' - (string) Class (由new Class创建, 或由其他Class对象扩展而来)
	//	'collection' - (string) 原生htmlelements集合, 如由方法childNodes, getElementsByTagName等获取到的结果
	//	'window' - (string) window 对象
	//	'document' - (string) document 对象
	//	'event' - (string) 事件(event)对象
	//	false - (boolean) undefined, null, NaN 或以上列出的类型都不是
	//
	// Examples: 
	//	var myString = 'hello';
	//	typeOf(myString); // 返回 "string".
	var typeOf = this.typeOf = function (item) {
		if (item == null) { return 'null'; }
		// 对于存在定义了$family方法的则返回其返回值,在接下来的Type基类的定义可以看到
		if (item.$family != null) { return item.$family(); }

		if (item.nodeName) {
			if (item.nodeType == 1) { return 'element'; }
			// 对于文本节点，再确定其是否为只包含空格(包括\n等分隔符)
			if (item.nodeType == 3) { return (/\S/).test(item.nodeValue) ? 'textnode' : 'whitespace'; }
			// 有人可能会问那2是什么呢，2是属性节点一般不会用到
		} else if (typeof item.length == 'number') {
			// 对于每个函数(方法)都有隐藏的类数组局部变量arguments在函数运行时产生（可以通过遍历使之成为真正数组）
			// 并成为其此函数活动对象的一部分（活动对象还包括外层的变量等等，具体参考javascript高级程序设计）
			// 相应的，arguments也有一个相对不常用的属性callee指向使用它的这个函数(方法)，在函数自迭代中经常会使用到
			if (item.callee) { return 'arguments'; }
			// 如果对象中有包含item属性则视其为集合对象collection
			if ('item' in item) { return 'collection'; }
		}

		return typeof item;
	};

	// 检查一个对象是否是一个特定类型的实例
	//
	// Syntax: instanceOf(item, object)
	//
	// Arguments: 
	//	item - (mixed) 要检查的对象
	//	object - (mixed) 要比较的类型
	//
	// Returns: 
	//	(boolean) 对象是否是这个类型的实例
	//
	// Examples: 
	//	var foo = [];
	//	instanceOf(foo, Array)  // 返回 true
	//	instanceOf(foo, String) // 返回 false
	//
	//	var myClass = new Class();
	//	var bar = new myClass();
	//
	//	instanceOf(bar, myClass)    // 返回 true
	var instanceOf = this.instanceOf = function (item, object) {
		if (item == null) { return false; }
		// 判断是否可以通过迭代追溯到object，如果可以则返回true
		var constructor = item.$constructor || item.constructor;
		while (constructor) {
			if (constructor === object) { return true; }
			constructor = constructor.parent;
		}
		//如果不行，则通过原生js判断
		return item instanceof object;
	};

	// #endregion

	// #region - 扩充Funciton对象原型方法(extend, implement) -

	/**
	* 由于很多对function操作都是以调用相关方法的形式进行，所以在这里会先扩展Function类的部分原型方法
	* (一切对构造函原型的扩展等同对所有实例的扩展,这个就不赘述了)，
	* 这里先对IE不能遍历对象中类似toString方法的bug做一个修正。
	**/
	var Function = this.Function;

	// 有些浏览器不会枚举Object中定义部分属性即使重新在对象中定义了这些属性,比如toString主要是IE。
	var enumerables = true;
	for (var i in { toString: 1 }) {
		enumerables = null;
	}
	// 如果遍历不到则enumerables为true，需要将这些有些浏览器会遗忘的属性暂存起来。
	if (enumerables) {
		enumerables = ['hasOwnProperty', 'valueOf', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'constructor'];
	}

	/**
	* 然后就会对function两个非常重要的工具方法overloadSetter与overloadGetter，两个方法顾名思义
	*
	* overloadSetter使得一个类似setStyle(name,value)的方法接受一个对象字面形式的参数即
	* {name1:value1,name2:value2}分别将属性值作用于属性名(如何作用取决于原来未被overload的方法，
	* 如果setStyle则相当于同时处理了多个style的属性)
	*
	* overloadGetter使得一个类似getStyle(name)的方法(本来返回value)接受一个数组参数
	* 如[name1,name2,name3]，然后返回一个返回值的字面量对象如{name1:value1,name2:value,name3:value3}。
	*
	* 这两个方法非常重要后面经常会用到(事实上这两个方法都是暴露出来的，而官方的API是不会把这种生涩难懂的接口公开的，所以学习源码也是进一步学习这个库的重要途径)，具体实现都用到了函数curry化:
	**/

	// overloadSetter可以让一个已经设定好的函数接受json形式的参数，即func(a,b)也可以是func({a:b,c:d})，进行多重赋值操作
	Function.prototype.overloadSetter = function (usePlural) {
		// 外层函数this引用赋予另一个局部变量self,使得函数内层函数可以通过这个变量访问这个this引用，
		// 这里this指向一个function对象（它的构造函数为Function）
		var self = this;

		// 返回加强过的函数
		return function (a, b) {
			if (a == null) { return this; }
			// 判断参数是否为对象字面量
			if (usePlural || typeof a != 'string') {
				// 这句是关键，调用多次自身,完成方法增强
				for (var k in a) {
					self.call(this, k, a[k]);
				}
				// 如果是在无法枚举到toString等方法的
				if (enumerables) {
					/**
					# 苦苦的苦瓜 
					# 2011-10-12
					# for循环改为while循环
					# for (var i = enumerables.length; i--; ) {
					**/
					var i = enumerables.length;
					while (i--) {
						k = enumerables[i];
						// 如果a中包含有不能枚举的属性(（但是已经在对象中定义了hasOwnProperty(k)），则运行
						if (a.hasOwnProperty(k)) {
							self.call(this, k, a[k]);
						}
					}
				}
			} else {
				// 对于常规形式(即a为字符串)不作变动
				self.call(this, a, b);
			}
			return this;
		};
	};

	// overloadGetter可以让一个已经定义好的函数接受json形式的参数，
	// 即func(a)也可以是func([a,b]),但是这样会返回一个result数组。
	Function.prototype.overloadGetter = function (usePlural) {
		var self = this;
		return function (a) {
			var args, result;
			// 如果参数不是string类型
			if (usePlural || typeof a != 'string') {
				args = a;
			} else if (arguments.length > 1) {
				// 这里就稍微繁杂了点了，接受形如 name1,[name2,name3],name4类型的参数
				args = arguments;
			}
			if (args) {
				result = {};
				// 将每个返回值传入返回的字面量对象中,这里会完成一次循环遍历操作,即参数中仍有可能仍为数组
				for (var i = 0; i < args.length; i++) {
					result[args[i]] = self.call(this, args[i]);
				}
			} else {
				// 如果常规形式则不作变动
				result = self.call(this, a);
			}
			return result;
		};
	};

	/**
	* 接下来又是两个对Function及其重要的原型扩展 extend (扩展function的静态方法)和implement
	* (扩展function的实例方法)两者都是后面多次重写的implement以及的extend的基础。
	* 
	* 在这里你只要记住extend则是针对其本身的扩充,implement(通过扩展原型)则是针对其实例所作的扩充。
	* 
	* 这里需要提醒的就是所有的构造函数都可以视为function类型(包括Function本身，
	* 即可以通过Function.implement扩充其原型！！！儿子的父亲是它的兄弟…js真的太奇妙了)
	**/

	// 这个方法可以添加function类型对象的静态方法，即可以通过func.key(args)的方式调用这个静态方法。
	Function.prototype.extend = function (key, value) {
		this[key] = value;
	} .overloadSetter();

	// 这个方法可以添加function的原型对象的方法，即实例方法即可以通过(new func()).key(args)的方式调用这个方法。
	Function.prototype.implement = function (key, value) {
		this.prototype[key] = value;
	} .overloadSetter();

	// #endregion 扩充Funciton对象extend implement

	// #region - 扩充原生对象的静态方法(From) -

	// 扩展了各个原生类型的from来强制转换类型(包括几个没有强制转换机制的,比如Function)

	// 一个slice的简写
	var slice = Array.prototype.slice;

	// Function的静态方法，如果item为function则Function.from(item)返回item方法，否则返回一个返回值是item的匿名方法。
	// 
	// Syntax: var foo = Function.from(obj);
	// 
	// Arguments: 
	//	obj - (mixed) If this argument is a function, it will simply return itself. Otherwise, an object you wish to convert into a function that returns the argument.
	// 
	// Returns: 
	//	(function) Either the passed function or an anonymous function that returns the passed argument
	// 
	// Examples: 
	//	var fn = Function.from(42);
	//	alert(fn());    // alerts '42'
	// 
	//	var fn2 = Function.from(fn);
	//	alert(fn2());   // alerts '42'
	// 
	Function.from = function (item) {
		return (typeOf(item) == 'function') ? item : function () {
			return item;
		};
	};

	// 如果传入的参数不是一个数组, 则将其包装成一个数组
	// Array的静态方法，假如item为数组或者类数组（可枚举，如ElementConlection等）返回数组，
	// 否则传回[item]即单元素数组。
	// 
	// Syntax: var splatted = Array.from(obj);
	// 
	// Arguments: 
	//	obj - (mixed) 任意类型的变量
	// 
	// Returns: 
	//	(array) 如果传入的参数是个数组, 那么返回该数组; 否则, 返回一个包含传入参数的数组.
	// 
	// Examples: 
	//	Array.from('hello'); // 返回 ['hello'].
	//	Array.from(['a', 'b', 'c']); // 返回 ['a', 'b', 'c'].
	// 
	Array.from = function (item) {
		if (item == null) { return []; }
		return (Type.isEnumerable(item) && typeof item != 'string') ? (typeOf(item) == 'array') ? item : slice.call(item) : [item];
	};

	// 如果item是可以转化为number的则返回转化后的数字，否则返回null。
	// 
	// Syntax: Number.from(arg);
	// 
	// Arguments: 
	//	arg - (mixed) The argument to return as a number
	// 
	// Returns: 
	//	(number) The argument as a number. 
	//	(null) Returns null if the number cannot be converted. 
	// 
	// Examples: 
	//	Number.from('12')       // returns 12
	//	Number.from('hello')    // returns null
	Number.from = function (item) {
		var number = parseFloat(item);
		return isFinite(number) ? number : null;
	};

	// 将传入参数转换为字符串
	// String的静态方法，如果item是可以转化为String的则返回转化后的字符串，
	// 
	// Syntax: String.from(arg);
	// 
	// Arguments: 
	//	arg - (mixed) 要转为字符串的参数
	// 
	// Returns: 
	//	(string) 参数转为的字符串
	// 
	// Examples: 
	//	String.from(2); // 返回 '2'
	//	String.from(true); // 返回 'true'
	String.from = function (item) {
		// 字符连接符'+'自动调用传入参数的toString()方法（继承自Object）。
		return item + '';
	};

	// #endregion 扩充原生对象的静态方法From

	// #region - 扩充Funciton对象原型方法(hide, protect) -

	/**
	* 按照前面extend,implement的定义，它会傻头傻脑的扩充静态方法或者原型对象的方法(跟实例方法一致的)，
	* 而实际的情况可能会复杂，比如原型对象中已经有同名方法了，覆盖还是不覆盖？或者说这个传入的方法的本
	* 身并不愿意被别人继承(不是类的继承,请自己分辨),你总不能逼良为娼吧..
	* 
	* 就在这时,之前提到的第一个儿子的父亲是他的兄弟的例子来了,Function开始implement了
	**/
	Function.implement({

		// hide()函数让一个function对象的$hidden属性设置为true（区别Function与function是构造函数
		// 与实例的关系）使之无法被其他对象implement
		hide: function () {
			this.$hidden = true;
			return this;
		},

		// protect()让一个function对象的$protect设为true，即它的方法无法被同名函数覆盖，
		// 比如已经存在object.func1方法，那这个对象在扩充时就无法覆盖它这个在下面才能看到他的用途。
		protect: function () {
			this.$protected = true;
			return this;
		}

	});

	// #endregion hide, protect

	// #region - Type Class -

	var Type = this.Type = function (name, object) {
		if (name) {
			// 统一将其设为小写，在判断type时就不用考虑大小写了
			var lower = name.toLowerCase();
			var typeCheck = function (item) {
				return (typeOf(item) == lower);
			};

			// 每当创建一个Type实例(如Class)，则给Type添加一个静态方法
			// (如isClass)来快速判断某个Type类型是不是Class类型
			Type['is' + name] = typeCheck;
			if (object != null) {
				// 这个$family函数在之前typeOf已经做了说明，加了hide即表示此
				// 函数不可在implement或者extend之时被覆盖
				object.prototype.$family = (function () {
					return lower;
				}).hide();
			}
		}

		/**
		* 并不是说return null就没有任何作用了,如果没有传入第二个参数 作用就是引入
		* 一个Type['is'+name],的检查类型的方法,虽然没有指定$family，对于比如Node类型的
		* 对象还是可以通过typeOf判断其类型,所以isTextNode等方法就可以用来快速判断了
		* 没听懂?给你个例子前面定义的typeOf中说明了dom节点或者文本节点可以通过其nodeType来
		* 得到返回值 如  new ('TextNode',null)这里事实上与实际上的textnode没有任何关系,但是却产生了
		* 一个isTextNode的方法,而isTextNode是typeOf的包装,这下明白了吧
		**/
		if (object == null) { return null; }

		// 这句非常重要!!!!!重新返回的object经过extend(this)之后就拥有了Type原型对象中的方法！！
		object.extend(this);
		// 将object的构造函数设为Type ，模拟的好像啊...
		object.$constructor = Type;
		//指定object的原型的$constructor使之 可以正确的instanceOf
		object.prototype.$constructor = object;

		// 返回了这个被包装过的类
		return object;
	};

	// 首先是个无关紧要的部分，仅仅为保证粘贴的完整性
	// toString的简写
	var toString = Object.prototype.toString;

	// Type的静态方法，判断一个参数是否是可枚举的
	Type.isEnumerable = function (item) {
		return (item != null && typeof item.length == 'number' && toString.call(item) != '[object Function]');
	};

	// #endregion Type Class

	// #region - hooks对象 -

	/**
	* 接下来就是hooks对象(纯洁的对象)了，它的所有键值对中的键就是对应一个Type类型的类的名(即typeOf之后的值，比
	* 如'person')，值则为对应的缓存函数数组，数组中存放着这些键名对应的类(如Person)在implement时应该处理的函数，
	* 在某个Type类型实例(如Person)通过implement扩充其原型时，将遍历这个它对应的数组并处理那些缓存的函数。
	* 
	* 如果这个函数为Type型的实例(假设是Person2)，则对其一并作implement处理，比如在扩充js内置类型Array的原型方
	* 法时，让Elements也享受到这些扩展(所以其实所有Array的方法，Elements都可以使用，
	* 而这点在官方的DOC中是没有提及的)。
	**/

	// 钩子，非常形象。这是一个字面量对象，缓存一些在即某个Type包装过的构造函数(如Person)
	// 扩充原型对象时需要一并处理的函数。
	// 一个typeOf得到的值为'person'的Type类型实例的缓存函数都缓存在名为hooks['person']的函数数组内。
	var hooks = {};

	// 这个函数用来返回某个Type类型实例对应的钩子函数组
	var hooksOf = function (object) {
		// hooksOf实际上在下面的应用时会作用于Type类型的类（如Person,注意大小写）
		// 而typeOf只能作用其实例(如person)所以要使用object.prototype
		var type = typeOf(object.prototype);
		// ~奇淫小技巧~，如果hooks[type]存在则返回它否则将其赋值为空数组再返回
		return hooks[type] || (hooks[type] = []);
	};

	// #endregion hooks对象

	// #region - Private Methods(implement, extend) -

	/**
	* 然后就是两个独立的(即不属于任何对象)工具函数的implement(它将会使用到刚才提到的hooks)
	* 以及extend(请与之前扩展Function时的implement与extend区分开来，这里要进化了)
	**/

	// 内部工具函数implement，虽然这是个独立的函数，但是接下来会被implement(这时使用的是Function的implements)
	// 到Type中,即所有类似Person的类都能使用这个工具函数了implement(最重要的方法之一)，
	// 所以这里的this你可以先看成是所有Type类的实例(如Person)
	var implement = function (name, method) {
		// $hidden的作用,请查看之前提到过的Function.prototype.hide()
		// 如果$hidden值为true则说明这个method不该被赋予给其他对象
		if (method && method.$hidden) { return; }

		// 这里this指代某个Type类型的类(如Person),hooksOf返回其对应的缓存函数数组
		var hooks = hooksOf(this);

		// 看上面的hooksOf的解释
		/**
		# 苦苦的苦瓜 
		# 2011-10-12
		# for循环改为while循环
		# for (var i = 0; i < hooks.length; i++) {
		**/
		var i = 0, l = hooks.length;
		while (i < l) {
			var hook = hooks[i++];
			// 如果放入这个钩子函数是Type类型, 则这个类型的原型对象也扩充传入的这个method。
			if (typeOf(hook) == 'type') {
				implement.call(hook, name, method);
			} else {
				// 否则运行这个钩子函数
				hook.call(this, name, method);
			}
		}

		// previous指代被扩展的类(如Person)的原型对象中的同名方法
		// 如果没有或者有但是不是受保护的则添加或修改相应的prototype[name]
		var previous = this.prototype[name];
		if (previous == null || !previous.$protected) {
			this.prototype[name] = method;
		}

		// 添加被扩展类(如Person)的静态方法，使得除了以实例方法的形式如person.func(args)调用也可以使用
		// Person.func(person,args)调用，(所以所有类似于[1,2,3].flatten()的方法可以用Array.flatten([1,2,3])调用)
		// (obj是constructor的实例)
		if (this[name] == null && typeOf(method) == 'function') {
			extend.call(this, name, function (item) {
				return method.apply(item, slice.call(arguments, 1));
			});
		}
	};

	// 内部工具函数extend 机理与上面一致
	var extend = function (name, method) {
		if (method && method.$hidden) { return; }
		var previous = this[name];
		if (previous == null || !previous.$protected) {
			this[name] = method;
		}
	};

	// #endregion Private Methods(implement, extend)

	// #region - 扩展Type -

	/**
	* 上面提到了hooks何时会被使用，但是hooks中的缓存方法什么时候放进去呢？答案是下面的Type基类将要implement的mirror方法！
	* 同时Type也implement了上面的两个独立函数，所以之后的implement与extend都开始指的是这两个：
	**/

	Type.implement({

		// 这几个是暴露出来的方法，需要牢记，都是相应的工具方法(上面)overloadSetter后的函数
		// 即可实现extend或者implement多个方法了
		implement: implement.overloadSetter(),

		extend: extend.overloadSetter(),

		// 对已经存在的原型对象中的方法做别名处理,即你可以通过
		// obj.name或者obj.existing来访问这个方法
		alias: function (name, existing) {
			implement.call(this, name, this.prototype[existing]);
		} .overloadSetter(),

		/**
		* 将hook（一般为一个函数）暂时存放在hooks[type]的数组中,不作处理,直到这个Type类型的构造函数implement的时候
		* 其中type是这个Type类型的构造函数指定的name属性
		* 如果传入hook为另外一个Type类型则在implement时另外一个Type类型也会被连带处理
		* mirror方法非常重要，相当于1.2中的afterImplement，比如Element类implement了一个方法 setStyle ，如果在连带的hook中处理了Elements
		* 那它implement的同时也会影响到Elements了！！！所以$$(".className").setStyle(xx,xx)是正确的语法!!!太高端了mootools
		* 对不起我又鸡动了\(≧▽≦)/
		**/
		mirror: function (hook) {
			hooksOf(this).push(hook);
			return this;
		}

	});

	/**
	* 先对Type做一个总结：简而言之，new Type(name,func)即仅仅只对输入的func做了一点加工，
	* 比如使其对typeOf以及instanceOf有效，使其可以使用implement以及extend,mirror等等方法。
	* 
	* 到这里Type的核心机制基本完结，开始在此基础上扩展JS的一些内置对象。如何处理?
	* 难道一并用new Type('String',String)这样粗暴的方式？当然不是...因为内置类型
	* 有很多自带的方法，这些方法应该被保护起来，使其不会被覆盖，这就引出了force方法。
	**/

	new Type('Type', Type);

	// Default Types

	// #endregion 扩展Type

	// #region - Private Method(force) -

	// force可以对一些内置类型(如String)做的一些处理，具体就是保护其静态方法，原型对象的方法。
	// 并将其包装成Type类，使其拥有extend，mirror等实用方法，并可以用typeOf以及instanceOf判断
	// (被force()过(第一反应翻译成被强暴过的人我从心底里的鄙视你)与被new Type()的效果是一样的)
	var force = function (name, object, methods) {
		var isType = (object != Object),
				prototype = object.prototype;

		// 只要不是Object（即原型js的始祖类）都对其做包装处理为什么不包装Object?
		// 而仅仅只是保护它的方法?因为Object牵连的太多了
		if (isType) {
			object = new Type(name, object);
		}

		// 遍历这个methods数组，检查是否有对应的原型对象方法proto或者静态方法generic
		/**
		# 苦苦的苦瓜 
		# 2011-10-12
		# for循环改为while循环
		# for (var i = 0, l = methods.length; i < l; i++) {
		**/
		var i = 0, l = methods.length;
		while (i < l) {
			var key = methods[i++],
					generic = object[key],
					proto = prototype[key];

			// 如果存在静态方法比如String.func,则保护这个方法,使其无法被覆盖
			if (generic) { generic.protect(); }

			// 如果存在原型对象方法 则将其设为protect
			if (isType && proto) {
				delete prototype[key];
				// 保护此原型对象方法
				prototype[key] = proto.protect();
			}
		}

		// 让原类型implement修改后的prototype即将一些方法设为了保护。
		if (isType) { object.implement(prototype); }

		// 返回函数本身，使其可以force()()()的连缀语法转换类型
		return force;
	};

	// 依次转换String，Array，Number,Function,RegExp,Object,Date内置类型，
	// 并保护列出的方法(Type结束之后将马上对他们进行扩展).这些原生js的方法也是常用的,
	// 如果不是完全清楚他们的作用,可以照此好好复习下。
	force('String', String, [
	'charAt', 'charCodeAt', 'concat', 'indexOf', 'lastIndexOf', 'match', 'quote', 'replace', 'search',
	'slice', 'split', 'substr', 'substring', 'trim', 'toLowerCase', 'toUpperCase'
])('Array', Array, [
	'pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice',
	'indexOf', 'lastIndexOf', 'filter', 'forEach', 'every', 'map', 'some', 'reduce', 'reduceRight'
])('Number', Number, [
	'toExponential', 'toFixed', 'toLocaleString', 'toPrecision'
])('Function', Function, [
	'apply', 'call', 'bind'
])('RegExp', RegExp, [
	'exec', 'test'
])('Object', Object, [
	'create', 'defineProperty', 'defineProperties', 'keys',
	'getPrototypeOf', 'getOwnPropertyDescriptor', 'getOwnPropertyNames',
	'preventExtensions', 'isExtensible', 'seal', 'isSealed', 'freeze', 'isFrozen'
])('Date', Date, ['now']);

	// #endregion Private Method(force)

	// #region - 扩充原声对象 -

	/**
	* 接下来开始扩充老大哥Object的静态方法(为什么不是原型对象方法?哥你醉了…)，
	* 需要注意的是，上面可以知道Object事实上并没有经过new Type()所以Object调用
	* 的extend等方法都是之前的Function的原型对象的extend而不是从Type继承而来的extend
	**/

	// 使得Oject.extend支持json格式的多重赋值，下面就不在赘述这个方法了
	Object.extend = extend.overloadSetter();

	//+new Date的效果与new Date().getTime()是一样的自动转换返回相应的距离1970元月的毫秒数
	//比如d=new Date；d-new Date()也可以自动转换,但d+new Date()是不行的！
	//这个方法返回当前时间的时间戳如1298029011401
	Date.extend('now', function () {
		return +(new Date);
	});

	// 包装Boolean，但是不对方法做保护处理
	new Type('Boolean', Boolean);

	// 修正NaN会返回number类型的问题(fixes NaN returning as Number)
	Number.prototype.$family = function () {
		return isFinite(this) ? 'number' : 'null';
	} .hide();

	// Number静态方法，Math.random()的加强版
	// Returns a random integer between the two passed in values.
	// 
	// Syntax: var random = Number.random(min, max);
	// 
	// Arguments: 
	//	min - (number) The minimum value (inclusive). 
	//	max - (number) The maximum value (inclusive). 
	// 
	// Returns: 
	//	(number) A random number between min and max. 
	// 
	// Examples: 
	//	Number.random(5, 20); // returns a random number between 5 and 20.
	// 
	Number.extend('random', function (min, max) {
		return Math.floor(Math.random() * (max - min + 1) + min);
	});

	// Object对象静态方法(forEach, each)，对对象中的键值对进行迭代
	// 
	// Syntax: Object.each(obj, fn[, bind]);
	// 
	// Arguments: 
	//	obj - (object) 被迭代的对象 
	//	fn - (function) 迭代过程中对每个迭代元素进行处理的函数 
	//		语法：fn(item, index, object)
	//		Arguments: 
	//			item - (mixed) 当前迭代项 
	//			index - (number) 当前迭代项的对应键值(对象属性名) 
	//			object - (mixed) 迭代对象 
	//	bind - (object, 可选) 迭代函数中'this'所应用的对象. 详见 Function:bind. 
	// 
	// Returns: N/A
	// 
	// Examples: 
	//	显示 'The first day of the week is Sunday', 'The second day of the week is Monday', 等等:
	//	Object.each({first: 'Sunday', second: 'Monday', third: 'Tuesday'}, function(value, key){
	//		alert('The ' + key + ' day of the week is ' + value);
	//	});
	var hasOwnProperty = Object.prototype.hasOwnProperty;
	Object.extend('forEach', function (object, fn, bind) {
		for (var key in object) {
			// 对于不是从构造函数的原型继承的属性，推入待运行的函数fn作为其参数。
			if (hasOwnProperty.call(object, key)) {
				fn.call(bind, object[key], key, object);
			}
		}
	});
	Object.each = Object.forEach;

	// 迭代数组(包括非常规数组,如由内建的getElementsByTagName方法返回的集合对象, arguments对象, 或Ojbect对象) 
	// 
	// Syntax: Array.each(iterable, fn[, bind]);
	// 
	// Arguments: 
	//	iterable - (array) 被迭代的对象 
	//	fn - (function) 迭代过程中对每个迭代元素进行处理的函数 
	//		语法：fn(item, index, object)
	//		Arguments: 
	//			item - (mixed) 当前迭代项 
	//			index - (number) 当前迭代项的索引. 如果迭代对象是一个Oject对象, 则是对象的属性名 
	//			object - (mixed) 迭代对象
	//	bind - (object, 可选) 迭代函数中'this'所引用的对象. 详见 Function:bind. 
	// 
	// Returns: N/A
	// 
	// Examples: 
	//	Array.each(['Sun', 'Mon', 'Tue'], function(day, index){
	//		alert('name:' + day + ', index: ' + index);
	//	}); // 显示 'name: Sun, index: 0', 'name: Mon, index: 1', 等等.
	// 
	// Calls a function for each element in the array(对数组进行迭代处理)
	// 
	// Syntax: myArray.each(fn[, bind]);
	// 
	// Arguments: 
	//	fn - (function) The function which should be executed on each item in the array. This function is passed the item and its index in the array.
	//			 (每次迭代中执行的函数. 当前迭代项及它的索引号将被作为参数传入该函数)
	//		语法：fn(item, index, array)
	//		Arguments: 
	//			item - (mixed) The current item in the array.
	//			index - (number) The current item's index in the array.
	//			array - (array) The actual array.
	//	bind - (object, optional) The object to be used as 'this' in the function. For more information see Function:bind.
	//					                  函数中this所引用的对象. 详见 Function:bind . 
	// 
	// Returns: N/A
	// 
	// Examples: 
	//	//Alerts "0 = apple", "1 = banana", and so on:
	//	['apple', 'banana', 'lemon'].each(function (item, index) {
	//		alert(index + " = " + item);
	//	}); //The optional second argument for binding isn't used here.
	Array.implement({
		// 可以通过i in this判断是否存在于数组中，但是不推荐
		// 使用 for (var key in array)遍历数组，可能遍历出杂乱无章的属性
		forEach: function (fn, bind) {
			for (var i = 0, l = this.length; i < l; i++) {
				if (i in this) {
					fn.call(bind, this[i], i, this);
				}
			}
		},

		each: function (fn, bind) {
			Array.forEach(this, fn, bind);
			return this;
		}

	});

	// Array & Object cloning, Object merging and appending
	// Array以及Object的clone方法的定义,这里可以看到js中方法的定义是相当灵活的。
	// 满足条件的话可以你中有我,我中有你......当然也带来了阅读的难度
	var cloneOf = function (item) {
		switch (typeOf(item)) {
			case 'array':
				return item.clone();

			case 'object':
				return Object.clone(item);

			default:
				return item;
		}
	};

	// 返回传入数组的一个克隆数组
	// 
	// Syntax: var clone = Array.clone(myArray);
	// 
	// Arguments: 
	//	myArray - (array) 要克隆的数组
	// 
	// Returns: 
	//	(array) 传入数组的一个克隆数组
	// 
	// Examples: 
	//	var myArray = ['red', 'blue', 'green'];
	//	var otherArray = Array.clone(myArray);
	//	 
	//	var myArray[0] = 'yellow';
	//
	//	alert(myArray[0]);      // 显示 'yellow'
	//	alert(otherArray[0])    // 显示 'red'
	Array.implement('clone', function () {
		var i = this.length,
				clone = new Array(i);
		while (i--) {
			clone[i] = cloneOf(this[i]);
		}
		return clone;
	});

	//实现Object.merge的工具方法，同样的两个方法你中有我，我中有你...
	var mergeOne = function (source, key, current) {
		switch (typeOf(current)) {
			case 'object':
				if (typeOf(source[key]) == 'object') {
					Object.merge(source[key], current);
				} else {
					source[key] = Object.clone(current);
				}
				break;

			case 'array':
				source[key] = current.clone();
				break;

			default: source[key] = current;
		}
		return source;
	};

	Object.extend({

		// 合并一组对象生成新对象
		// 通过操作副本不破坏原来对象的情况下，吞并多个对象内容，如果第二个参数为string类型,则只吞并k: v 这种形式的属性对。
		// 即接受(obj1,obj2,obj3)产生的obj为obj1并带有后面两个对象的属性，重复属性被后者覆盖
		// 也接受(obj1,str,mix) ==>mix指的任意类型，这样返回的obj1多了一条形如  str:  mix 的属性
		// 
		// Syntax: var merged = Object.merge(obj1, obj2[, obj3[, ...]]);
		// 
		// Arguments: 
		//	(objects) 任意数量的对象
		// 
		// Returns: 
		//	(object) 合并生成的新对象 
		// 
		// Examples: 
		//	var obj1 = {a: 0, b: 1};
		//	var obj2 = {c: 2, d: 3};
		//	var obj3 = {a: 4, d: 5};
		//	var merged = Object.merge(obj1, obj2, obj3); // 返回新对象 {a: 4, b: 1, c: 2, d: 5}, (obj2 和 obj3 未被改变)
		//	merged === obj1; // 表达式值为 true, obj1 被改变，作为合并后的对象被返回
		//	
		//	var nestedObj1 = {a: {b: 1, c: 1}};
		//	var nestedObj2 = {a: {b: 2}};
		//	var nested = Object.merge(nestedObj1, nestedObj2); // 返回: {a: {b: 2, c: 1}}
		merge: function (source, k, v) {
			if (typeOf(k) == 'string') {
				return mergeOne(source, k, v);
			}
			/**
			# 苦苦的苦瓜 
			# 2011-10-12
			# for循环改为while循环
			# for (var i = 1, l = arguments.length; i < l; i++) {
			**/
			var i = 1, l = arguments.length;
			while (i < l) {
				var object = arguments[i++];
				for (var key in object) {
					mergeOne(source, key, object[key]);
				}
			}
			return source;
		},

		// 返回对象的一个拷贝
		// 
		// Syntax: var clone = Object.clone(obj);
		// 
		// Arguments: 
		//	(obj) 要克隆的对象
		// 
		// Returns: 
		//	(object) 传入对象的一个拷贝
		// 
		// Examples: 
		//	var obj1 = {a: 0, b: 1};
		//	var obj2 = Object.clone(obj1);
		//	obj1.a = 42;
		//	alert(obj1.a);  // 显示 '42'
		//	alert(obj2.a);  // 显示 '0'
		clone: function (object) {
			var clone = {};
			for (var key in object) {
				clone[key] = cloneOf(object[key]);
			}
			return clone;
		},

		// 将第二个参数对象的所有属性复制到第一个参数对象中
		// 
		// Syntax: Object.append(original, extension);
		// 
		// Arguments: 
		//	original - (object) 目标对象 
		//	extension - (object) 源对象
		// 
		// Returns: 
		//	(object) 复制属性后的第一个参数对象
		// 
		// Examples: 
		//	var firstObj = {
		//		name: 'John',
		//		lastName: 'Doe'
		//	};
		//	var secondObj = {
		//		age: '20',
		//		sex: 'male',
		//		lastName: 'Dorian'
		//	};
		//	Object.append(firstObj, secondObj);
		//	// firstObj 变成了: {name: 'John', lastName: 'Dorian', age: '20', sex: 'male'};
		// 
		append: function (original) {
			/**
			# 苦苦的苦瓜 
			# 2011-10-12
			# for循环改为while循环
			# for (var i = 1, l = arguments.length; i < l; i++) {
			**/
			var i = 1, l = arguments.length;
			while (i < l) {
				var extended = arguments[i++] || {};
				for (var key in extended) {
					original[key] = extended[key];
				}
			}
			return original;
		}

	});

	// 之前提到过 new Type(name,object) 可以不传入第二个参数而仅仅传入name。
	// 造成此那么代表的对象被包装的假象，事实只是为了提供一个isXXX的方法

	// Object-less types
	//包装不传入Type(name,object)中其中的object参数的对象，创建它们的isXXX的检查方法
	//在上面的12条重要注释我已经做了解释，为什么要这么传入空对象的原因
	['Object', 'WhiteSpace', 'TextNode', 'Collection', 'Arguments'].each(function (name) {
		new Type(name);
	});

	// Unique ID

	var UID = Date.now();

	// 产生一个唯一的ID
	// 
	// Syntax: String.uniqueID();
	// 
	// Arguments: N/A
	// 
	// Returns: 
	//	(string) 一个唯一ID
	// 
	// Examples: 
	//	String.uniqueID();
	// 
	String.extend('uniqueID', function () {
		/**
		* 非常精巧的一个Uid生成方法...Date.now()产生一个的13位的10进制数字
		* 通过toString(36)即转化为36进制 并将数字转化为string.计算一下大概会传回
		* 长度为8的string 形如gkb39bur  (英文字母26+数字10正好是36个！！！不会溢出精巧吧)
		* 当然仅仅只是观赏性较强....前面几位基本是不会动的.
		**/
		return (UID++).toString(36);
	});

	// #endregion 扩充原声对象

	// #endregion

	// #region -- Types --

	// #region - Array -

	/*
	---

	name: Array

	description: Contains Array Prototypes like each, contains, and erase.

	license: MIT-style license.

	requires: Type

	provides: Array

	由于是对Array的原型对象的扩展，所以这里的this指代一个数组
	这里我会多次提到返回值计算为true等说法，意思就是此值在布尔环境下值自动转换为true
	比如 if(scope)if语句中的scope就为布尔环境非空字符串，非0数字等等非bool值都自动转换为true

	...
	*/

	Array.implement({

		// #region -- !ES5 --

		// 如果数组中的每一项都通过给定函数的测试, 则返回 true . 这个方法只提供给没有原生 Array:every 方法支持的浏览器
		// 
		// Syntax: var allPassed = myArray.every(fn[, bind]);
		// 
		// Arguments: 
		//	fn - (function) 用来测试每一个数组项的函数 
		//		Syntax: 
		//			fn(item, index, array)
		//		Arguments: 
		//			item - (mixed) 当前迭代项 
		//			index - (number) 当前索引号 
		//			array - (array) 迭代的数组 
		//	bind - (object, 可选) 函数中this所引用的对象. 详情请参看 Function:bind . 
		// 
		// Returns: 
		//	(boolean) 如果数组中的每一项都通过给定函数的测试, 则返回 true ; 否则, 返回 false . 
		// 
		// Examples: 
		//	var areAllBigEnough = [10, 4, 25, 100].every(function(item, index){
		//		return item > 20;
		//	}); // areAllBigEnough = false
		every: function (fn, bind) {
			//l=this.length ,避免多次计算length值
			for (var i = 0, l = this.length >>> 0; i < l; i++) {
				// i in this 确认这个数组下标是否有效，什么意思？做如下测试var e=[1,,3,4,5];  console.log(1 in e)
				// 返回false(注意只有未定义为返回false，定义了即使是null等都返回的true)
				if ((i in this) && !fn.call(bind, this[i], i, this)) { return false; }
			}
			return true;
		},

		// 将所有在给定过滤函数中过滤通过的数组项创建一个新数组. 这个方法只提供给没有原生 Array:filter 方法支持的浏览器. 
		// 
		// Syntax: var filteredArray = myArray.filter(fn[, bind]);
		// 
		// Arguments: 
		//	fn - (function) 用来测试每一个数组项的函数, 当前迭代项以及它的索引号将被作为参数传入该函数. 
		//		Syntax: 
		//			fn(item, index, array)
		//		Arguments: 
		//			item - (mixed) 当前迭代项 
		//			index - (number) 当前索引号 
		//			array - (array) 迭代的数组 
		//	bind - (object, 可选) 函数中this所引用的对象. 详情请参看 Function:bind . 
		// 
		// Returns: 
		//	(array) 过滤后的新数组
		// 
		// Examples: 
		//	var biggerThanTwenty = [10, 3, 25, 100].filter(function(item, index){
		//		return item > 20;
		//	}); // biggerThanTwenty = [25, 100]
		filter: function (fn, bind) {
			var results = [];
			for (var i = 0, l = this.length >>> 0; i < l; i++) {
				if ((i in this) && fn.call(bind, this[i], i, this)) { results.push(this[i]); }
			}
			return results;
		},

		// 返回数组中和给出参数值相等的项的索引号; 如果未找到相等的项, 则返回 -1 . 这个方法只提供给没有原生 Array:indexOf 方法支持的浏览器. 
		// 
		// Syntax: var index = myArray.indexOf(item[, from]);
		// 
		// Arguments: 
		//	item - (object) 目标搜索项 
		//	from - (number, 可选: 默认值为0) 在数组中搜索的起始索引号 
		// 
		// Returns: 
		//	(number) 数组中和给出参数值相等的项的索引号; 如果未找到相等的项, 则返回 -1 
		// 
		// Examples: 
		//	['apple', 'lemon', 'banana'].indexOf('lemon'); // 返回 1
		//	['apple', 'lemon'].indexOf('banana'); // 返回 -1	
		indexOf: function (item, from) {
			var length = this.length >>> 0;
			// 如果from 小于0 则从结尾开始算(类似slice方法的参数处理方式)
			for (var i = (from < 0) ? Math.max(0, length + from) : from || 0; i < length; i++) {
				if (this[i] === item) { return i; }
			}
			return -1;
		},

		// 返回一个由经过给定函数处理返回的值所创建的新数组. 这个方法只提供给没有原生 Array:map 方法支持的浏览器
		// 
		// Syntax: var mappedArray = myArray.map(fn[, bind]);
		// 
		// Arguments: 
		//	fn - (function) 用来处理当前迭代项并返回新值的函数 
		//		Syntax: 
		//			fn(item, index, array)
		//		Arguments: 
		//			item - (mixed) 当前迭代项 
		//			index - (number) 当前索引号 
		//			array - (array) 迭代的数组 
		//	bind - (object, 可选) 函数中this所引用的对象. 详情请参看 Function:bind . 
		// 
		// Returns: 
		//	(array) 处理后的新数组 
		// 
		// Examples: 
		//	var timesTwo = [1, 2, 3].map(function(item, index){
		//		return item * 2;
		//	}); //timesTwo = [2, 4, 6];
		map: function (fn, bind) {
			var length = this.length >>> 0, results = Array(length);
			for (var i = 0; i < length; i++) {
				if (i in this) { results[i] = fn.call(bind, this[i], i, this); }
			}
			return results;
		},

		// 如果数组中至少有一个项通过了给出的函数的测试, 则返回 true . 这个方法只提供给没有原生 Array:some 方法支持的浏览器
		// 
		// Syntax: var somePassed = myArray.some(fn[, bind]);
		// 
		// Arguments: 
		//	fn - (function) 用于测试数组项的函数. 当前数组中的迭代项以及它在数组中的索引号将被传入该函数中. 
		//		Syntax: 
		//			fn(item, index, array)
		//		Arguments: 
		//			item - (mixed) 当前迭代项 
		//			index - (number) 当前索引号 
		//			array - (array) 迭代的数组 
		//	bind - (object, 可选) 函数中this所引用的对象. 详情请参看 Function:bind. 
		// 
		// Returns: 
		//	(boolean) 如果数组中至少有一个项通过了给出的函数的测试, 则返回 true ; 否则返回 false 
		// 
		// Examples: 
		//	var isAnyBigEnough = [10, 4, 25, 100].some(function(item, index){
		//		return item > 20;
		//	}); // isAnyBigEnough = true
		some: function (fn, bind) {
			for (var i = 0, l = this.length >>> 0; i < l; i++) {
				if ((i in this) && fn.call(bind, this[i], i, this)) { return true; }
			}
			return false;
		},

		// #endregion !ES5

		// 返回一个由原数组中计算值为true(即不是以下情况的值: null, undefined)的项，清理数组中所有值为null或者为未定义的元素
		// 
		// Syntax: var cleanedArray = myArray.clean();
		// 
		// Arguments: N/A
		// 
		// Returns: 
		//	(array) 过滤后的新数组
		// 
		// Examples: 
		//	var myArray = [null, 1, 0, true, false, 'foo', undefined, ''];
		//	myArray.clean() // 返回 [1, 0, true, false, 'foo', '']
		clean: function () {
			// 参考filter，由于undefined==null（自己测试下就知）
			// 所以也会同时清理未定义的元素
			return this.filter(function (item) {
				return item != null;
			});
		},

		// 遍历数组的各个成员, 执行其上定义的一个方法, 返回结果组成的数组
		// 
		// Syntax: var arr = myArray.invoke(method[, arg, arg, arg ...])
		// 
		// Arguments: 
		//	method - (string) 要迭代数组成员的方法名称 
		//	arg - (mixed) 该方法所需的参数 
		// 
		// Returns: 
		//	(array) 执行结果组成的数组
		// 
		// Examples: 
		//	var foo = [4, 8, 15, 16, 23, 42];
		//	var bar = foo.invoke('limit', 10, 30);  //bar is now [10, 10, 15, 16, 23, 30]
		// 
		// 提示：
		//	使用的方法应该是每个成员都拥有的. 如果某个成员的该方法不存在, 将会抛出异常. 举例: 
		//	[0, false, 'string'].invoke('limit', 0, 10); // 抛出一个异常!
		invoke: function (methodName) {
			//  取出methodName参数之后的所有参数形成一个数组
			var args = Array.slice(arguments, 1);
			// map方法会在接下来定义这里必须确保数组中的所有成员都
			// 必须拥有名为methodName的方法,否则报错
			return this.map(function (item) {
				// 依次运行数组元素的指定名称的方法
				return item[methodName].apply(item, args);
			});
		},

		// 创建一个键值对对象, 该对象中的键由作为参数传入的一个数组决定, 值由主调数组决定
		// 
		// Syntax: var associated = myArray.associate(obj);
		// 
		// Arguments: 
		//	obj - (array) 作为键源的数组
		// 
		// Returns: 
		//	(object) 合成后的键值对对象
		// 
		// Examples: 
		//	var animals = ['Cow', 'Pig', 'Dog', 'Cat'];
		//	var sounds = ['Moo', 'Oink', 'Woof', 'Miao'];
		//	sounds.associate(animals);// 返回 {'Cow': 'Moo', 'Pig': 'Oink', 'Dog': 'Woof', 'Cat': 'Miao'}
		associate: function (keys) {
			// 新对象的键值对个数由两数组的长度的最小值确定
			var obj = {}, length = Math.min(this.length, keys.length);
			for (var i = 0; i < length; i++) {
				obj[keys[i]] = this[i];
			}
			return obj;
		},

		// 根据给出的 “键/测试函数”对 来创建一个新的键值对对象
		// 这个方法将这个数组与一个对象做连接，这个对象中的每个值都是一个过滤函数, 创建一个新对象result，
		// 将传入的object键作为键，而原数组满足object值代表的过滤函数的第一个数组元素作为result的值，
		// 并返回result，看似强大,其实这个方法基本不会去用他..
		// 
		// Syntax: var result = myArray.link(object);
		// 
		// Arguments: 
		//	object - (object) 包含 “键/测试函数” 的对象
		// 
		// Returns: 
		//	(object) 新创建的键值对对象
		// 
		// Examples: 
		//	var el = document.createElement('div');
		//	var arr2 = [100, 'Hello', {foo: 'bar'}, el, false];
		//	arr2.link({
		//		myNumber: Type.isNumber,
		//		myElement: Type.isElement,
		//		myObject: Type.isObject,
		//		myString: Type.isString,
		//		myBoolean: function(obj){ return obj != null; }
		//	});
		//	// 返回 {myNumber: 100, myElement: el, myObject: {foo: 'bar'}, myString: 'Hello', myBoolean: false}
		//	// 备注说明: 当前键的取值搜索范围是前一个键的测试挑选剩余后的数组项(而不是整个数组项)
		link: function (object) {
			var result = {};
			for (var i = 0, l = this.length; i < l; i++) {
				for (var key in object) {
					// object[key](this[i])即运行每个object中的函数
					if (object[key](this[i])) {
						result[key] = this[i];
						delete object[key];
						break;
					}
				}
			}
			return result;
		},

		// 测试指定项是否在数组中存在
		// 
		// Syntax: var inArray = myArray.contains(item[, from]);
		// 
		// Arguments: 
		//	item - (object) 要进行测试的项 
		//	from - (number, 可选: 默认值为0) 在数组中开始搜索的起始位索引
		// 
		// Returns: 
		//	(boolean) 如果数组包含给出的项, 则返回 true ; 否则返回 false
		// 
		// Examples: 
		//	['a', 'b', 'c'].contains('a'); // 返回 true
		//	['a', 'b', 'c'].contains('d'); // 返回 false
		contains: function (item, from) {
			return this.indexOf(item, from) != -1;
		},

		// 将传入的数组追加到当前数组的末尾
		// 这里需要注意的是[1,2,3].push([4,5])与[1,2,3].push.apply(this,[4,5])的结果
		// 是不同的, 这里使用到apply相当于实现了concat的效果
		// 
		// Syntax: var myArray = myArray.append(otherArray);
		// 
		// Arguments: 
		//	otherArray - (array) 纳入源数组
		// 
		// Returns: 
		//	(array) 纳入新项后的主调数组
		// 
		// Examples: 
		//	var myOtherArray = ['green', 'yellow'];
		//	['red', 'blue'].append(myOtherArray); // 返回 ['red', 'blue', 'green', 'yellow'];
		//	[0, 1, 2].append([3, [4]]); // [0, 1, 2, 3, [4]]
		append: function (array) {
			this.push.apply(this, array);
			return this;
		},

		// 返回数组最后一个元素
		// 
		// Syntax: myArray.getLast();
		// 
		// Arguments: N/A
		// 
		// Returns: 
		//	(mixed) 数组中的最后一项 
		//	(null) 如果是空数组, 则返回null 
		// 
		// Examples: 
		//	['Cow', 'Pig', 'Dog', 'Cat'].getLast(); // 返回 'Cat'
		getLast: function () {
			return (this.length) ? this[this.length - 1] : null;
		},

		// 返回从数组中随机抽取的一项
		// 
		// Syntax: myArray.getRandom();
		// 
		// Arguments: N/A
		// 
		// Returns: 
		//	(mixed) 从数组中随机抽取的一项; 如果是空数组, 则返回null
		// 
		// Examples: 
		//	['Cow', 'Pig', 'Dog', 'Cat'].getRandom(); // 返回 one of the items
		getRandom: function () {
			// 这个Number.random就是返回传入两个数字中间的一个随机数
			return (this.length) ? this[Number.random(0, this.length - 1)] : null;
		},

		// 向数组中添加一项, 如果该项在数组中已经存在, 则不再添加. (大小写与类型敏感)
		// 
		// Syntax: myArray.include(item);
		// 
		// Arguments: 
		//	item - (object) 目标添加项
		// 
		// Returns: 
		//	(array) 添加元素后的主调数组
		// 
		// Examples: 
		//	['Cow', 'Pig', 'Dog'].include('Cat'); // 返回 ['Cow', 'Pig', 'Dog', 'Cat']
		//	['Cow', 'Pig', 'Dog'].include('Dog'); // 返回 ['Cow', 'Pig', 'Dog']
		include: function (item) {
			if (!this.contains(item)) { this.push(item); }
			return this;
		},

		// 将主调数组和另一个数组进行组合(重复的项将不会加入, 大小写和类型敏感)
		// 
		// Syntax: myArray.combine(array);
		// 
		// Arguments: 
		//	array - (array) 将被组合的源数组
		// 
		// Returns: 
		//	(array) 组合后的主调数组
		// 
		// Examples: 
		//	var animals = ['Cow', 'Pig', 'Dog'];
		//	animals.combine(['Cat', 'Dog']); //animals = ['Cow', 'Pig', 'Dog', 'Cat'];
		combine: function (array) {
			/**
			# 苦苦的苦瓜 
			# 2011-10-12
			# for循环改为while循环
			# for (var i = 0, l = array.length; i < l; i++) {
			**/
			var i = 0, l = array.length;
			while (i < l) {
				this.include(array[i++]);
			}
			return this;
		},

		// 清理数组某个指定元素,如果出现多个也一并清除
		// 
		// Syntax: myArray.erase(item);
		// 
		// Arguments: 
		//	item - (object) 目标删除项
		// 
		// Returns: 
		//	(array) 进行删除后的主调数组
		// 
		// Examples: 
		//	['Cow', 'Pig', 'Dog', 'Cat', 'Dog'].erase('Dog') // 返回 ['Cow', 'Pig', 'Cat']
		//	['Cow', 'Pig', 'Dog'].erase('Cat') // 返回 ['Cow', 'Pig', 'Dog']
		erase: function (item) {
			/**
			# 苦苦的苦瓜 
			# 2011-10-12
			# for循环改为while循环
			# for (var i = this.length; i--; ) {
			**/
			var i = this.length;
			while (i--) {
				if (this[i] === item) { this.splice(i, 1); }
			}
			return this;
		},

		// 清空数组
		// 
		// Syntax: myArray.empty();
		// 
		// Arguments: N/A
		// 
		// Returns: 
		//	(array) 清空后的主调数组
		// 
		// Examples: 
		//	var myArray = ['old', 'data'];
		//	myArray.empty(); //myArray 变成 []
		empty: function () {
			// 很多人都不知道length并不是只读属性吧...与ElementCollection不同
			// string 的length也是只读的加入对于一个长度为n的数组，设置其length为n+m
			// 则后续m个新元素默认为undefined
			this.length = 0;
			return this;
		},

		// 将多维数组扁平化(即变为一维数组)
		// 
		// Syntax: myArray.flatten();
		// 
		// Arguments: N/A
		// 
		// Returns: 
		//	(array) 扁平化后的主调数组
		// 
		// Examples: 
		//	var myArray = [1,2,3,[4,5, [6,7]], [[[8]]]];
		//	var newArray = myArray.flatten(); //newArray 变成 [1,2,3,4,5,6,7,8]
		flatten: function () {
			var array = [];
			for (var i = 0, l = this.length; i < l; i++) {
				var type = typeOf(this[i]);
				// 首先清除null元素
				if (type == 'null') { continue; }
				// 如果不是array collection 或者arguments 就cancat这个元素 否则继续递归这个元素
				// 为什么要用concat因为 push会将数组作为一个元素添加 结果数组 concat则是分离出元素按序添加
				// 需要注意的concat只最多处理一维数组。
				array = array.concat((type == 'array' || type == 'collection' || type == 'arguments' || instanceOf(this[i], Array)) ? Array.flatten(this[i]) : this[i]);
			}
			return array;
		},

		// 返回传入数组中第一个非未定义的项; 如果全部未定义, 则返回 null
		// 选取第一个结果不为null或undefined的元素. unshift的条件版...
		// 
		// Syntax: var picked = [var1, var2, var3].pick();
		// 
		// Arguments: N/A
		// 
		// Returns: 
		//	(mixed) 第一个非未定义的项 
		//	(null) 如果都是 null 或 undefined , 则返回 null
		// 
		// Examples: 
		//	function say(infoMessage, errorMessage){
		//		alert([errorMessage, infoMessage, 'There was no message supplied.'].pick());
		//		//或者 MooTools 1.2 的使用风格
		//		Array.pick([errorMessage, infoMessage, 'There was no message supplied.']);
		//	}
		//	say(); // 显示 'There was no message supplied.'
		//	say('This is an info message.'); // 显示 'This is an info message.'
		//	say('This message will be ignored.', 'This is the error message.'); // 显示 'This is the error message.'
		pick: function () {
			for (var i = 0, l = this.length; i < l; i++) {
				if (this[i] != null) { return this[i]; }
			}
			return null;
		},

		// 注意：使用这个函数时必须加载core.string
		// 将十六进制的颜色代码转换成RGB格式的代码. 输入的RGB代码需要类似如下的16进制格式: ['FF', 'FF', 'FF']
		// 将一个三元素数组的值(必须为string)转化为三色值推入rgb语句，如果传入参数array计算值为true则返回处理后的数组
		// 
		// Syntax: myArray.hexToRgb([array]);
		// 
		// Arguments: 
		//	array - (boolean, 可选) 是否输出为数组. 如果为 true , 则输出的RGB格式的颜色将是数组格式 (如 [255, 51, 0])而不是原本的字符串形式(如 "rgb(255, 51, 0)")
		// 
		// Returns: 
		//	(string) RGB格式的颜色代码字符串 
		//	(array) 如果设置了输出格式为数组, 则返回数组格式的RGB颜色代码
		// 
		// Examples: 
		//	['11', '22', '33'].hexToRgb(); // 返回 'rgb(17, 34, 51)'
		//	['11', '22', '33'].hexToRgb(true); // 返回 [17, 34, 51]
		hexToRgb: function (array) {
			if (this.length != 3) { return null; }
			var rgb = this.map(function (value) {
				if (value.length == 1) { value += value; }
				// str.toInt将string转化为int,默认以10进制转化
				return value.toInt(16);
			});
			// [1,2,3].toString()的结果是'1,2,3'所以下面的输出是正确的
			return (array) ? rgb : 'rgb(' + rgb + ')';
		},

		// 将RGB格式的颜色代码转换成十六进制的代码. 输入的RGB代码需要类似如下的其中一种格式: [255,255,255] 或 [255,255,255,1]
		// 将一个数字型数组(10进制)转换为'#ffffff'的hex颜色值的形式，如果传入参数array计算值为true则返回处理后的数组
		// 
		// Syntax: myArray.rgbToHex([array]);
		// 
		// Arguments: 
		//	array - (boolean, 可选) 是否输出为数组. 如果为 true , 则输出的十六进制颜色将是数组格式(如: ['ff','33','00'] ), 而不是原本的字符串形式(如: "#ff3300" )
		// 
		// Returns: 
		//	(string) 字符串格式的十六进制颜色代码, 或者若主调数组是一个代表 rgba 的颜色代码(即除了R,G,B外,还有一个Alpha值), 且第四个值是 0 , 则返回 'transparent' (透明) 
		//	(array) 如果设置了输出格式为数组, 则返回数组格式的十六进制颜色代码
		// 
		// Examples: 
		//	[17, 34, 51].rgbToHex(); // 返回 '#112233'
		//	[17, 34, 51].rgbToHex(true); // 返回 ['11', '22', '33']
		//	[17, 34, 51, 0].rgbToHex(); // 返回 'transparent'
		rgbToHex: function (array) {
			if (this.length < 3) { return null; }
			// 如果有第四个元素并且为0（即为rgba模式）,则为transparent
			if (this.length == 4 && this[3] == 0 && !array) { return 'transparent'; }
			var hex = [];
			for (var i = 0; i < 3; i++) {
				var bit = (this[i] - 0).toString(16);
				hex.push((bit.length == 1) ? '0' + bit : bit);
			}
			return (array) ? hex : '#' + hex.join('');
		}

	});

	// #endregion

	// #region - String -

	/*
	---

	name: String

	description: Contains String Prototypes like camelCase, capitalize, test, and toInt.

	license: MIT-style license.

	requires: Type

	provides: String

	...
	*/

	String.implement({

		// 使用正则表达式对字符串进行匹配测试.
		// 
		// Syntax: myString.test(regex[, params]);
		// 
		// Arguments: 
		//	regex - (mixed) 要匹配的字符串或正则表达式 
		//	params - (string, 可选) 如果第一个参数regex是一个字符串, 则本参数可为任何正则表达式参数(注意, 参数'g'无效) 
		// 
		// Returns: 
		//	(boolean) 匹配成功, 返回 true 
		//	(boolean) 匹配失败, 返回 false 
		// 
		// Examples: 
		//	'I like cookies'.test('cookie'); // 返回 true
		//	'I like cookies'.test('COOKIE', "i"); // 返回 true (ignore case)
		//	'I like cookies'.test('cake'); // 返回 false
		test: function (regex, params) {
			return ((typeOf(regex) == 'regexp') ? regex : new RegExp('' + regex, params)).test(this);
		},

		// 检测字符串内是否包含参数所给出的字符串. 
		// 如果给出了separator(分隔符)这个参数, 则匹配时将把主字符串看作按分割符切分的一个列表, 然后将需要检测的字符串和这些列表项进行比较
		// 
		// Syntax: myString.contains(string[, separator]);
		// 
		// Arguments: 
		//	string - (string) 目标测试字符串 
		//	separator - (string, 可选) 分割字符串(如: ' ', ','等). 
		// 
		// Returns: 
		//	(boolean) 如果目标字符串在本字符串内, 则返回 true 
		//	(boolean) 如果目标字符串在本字符串内不存在, 则返回 false
		// 
		// Examples: 
		//	'a bc'.contains('bc'); // 返回 true
		//	'a b c'.contains('c', ' '); // 返回 true
		//	'a bc'.contains('b', ' '); // 返回 false
		contains: function (string, separator) {
			// 这里为何要separator + string + separator（在原string首尾加上分隔符）？因为匹配字符串可能出现在首尾
			return (separator) ? (separator + this + separator).indexOf(separator + string + separator) > -1 : String(this).indexOf(string) > -1;
		},

		// 清除字符串两端的空白字符串
		// 
		// Syntax: myString.trim();
		// 
		// Arguments: N/A
		// 
		// Returns: 
		//	(string) 清理后的字符串
		// 
		// Examples: 
		// '    i like cookies     '.trim(); // 返回 'i like cookies'
		trim: function () {
			return String(this).replace(/^\s+|\s+$/g, '');
		},

		// 清除整个字符串中多余的空白字符串
		// 
		// Syntax: myString.clean();
		// 
		// Arguments: N/A
		// 
		// Returns: 
		//	(string) 清理后的字符串
		// 
		// Examples: 
		// ' i      like     cookies      \n\n'.clean(); // 返回 'i like cookies'
		clean: function () {
			return String(this).replace(/\s+/g, ' ').trim();
		},

		// 将以连字符分隔的字符串转换成以大小写形式进行分隔的字符串
		// 
		// Syntax: myString.camelCase();
		// 
		// Arguments: N/A
		// 
		// Returns: 
		//	(string) 以大小写形式（骆驼式）进行分隔的字符串
		// 
		// Examples: 
		// 'I-like-cookies'.camelCase(); // 返回 'ILikeCookies'
		camelCase: function () {
			// 为什么要用\D? 因为\w 包括\d的
			return String(this).replace(/-\D/g, function (match) {
				return match.charAt(1).toUpperCase();
			});
		},

		// 将以大小写形式进行分隔的字符串转换成以字符分隔的字符串
		// 
		// Syntax: myString.hyphenate();
		// 
		// Arguments: N/A
		// 
		// Returns: 
		//	(string) 以连接字符号分隔的字符串
		// 
		// Examples: 
		// 'ILikeCookies'.hyphenate(); // 返回 'I-like-cookies'
		hyphenate: function () {
			return String(this).replace(/[A-Z]/g, function (match) {
				return ('-' + match.charAt(0).toLowerCase());
			});
		},

		// 将字符串中每个单词的首字母大写
		// 
		// Syntax: myString.capitalize();
		// 
		// Arguments: N/A
		// 
		// Returns: 
		//	(string) 转换后的字符串
		// 
		// Examples: 
		// 'i like cookies'.capitalize(); // 返回 'I Like Cookies'
		capitalize: function () {
			return String(this).replace(/\b[a-z]/g, function (match) {
				return match.toUpperCase();
			});
		},

		// 将字符串中对正则表达式敏感的字符进行转义
		// 
		// Syntax: myString.escapeRegExp();
		// 
		// Arguments: N/A
		// 
		// Returns: 
		//	(string) 转义后的字符串
		// 
		// Examples: 
		// 'animals.sheep[1]'.escapeRegExp(); // 返回 'animals\.sheep\[1\]'
		escapeRegExp: function () {
			// 为什么要\\  因为\在string中也是转义标志，也需要转义
			return String(this).replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1');
		},

		// 将字符串解析为一个数值, 并以给出的基准进制计算为一个十进制整数
		// 
		// Syntax: myString.toInt([base]);
		// 
		// Arguments: 
		//	base - (number, 可选) 基准进制(默认为10). 
		// 
		// Returns: 
		//	(number) 解析并计算后的数值. 
		//	(NaN) 如果字符串内容不是数值, 则返回 NaN 
		// 
		// Examples: 
		//	'4em'.toInt(); // 返回 4
		//	'10px'.toInt(); // 返回 10
		toInt: function (base) {
			return parseInt(this, base || 10);
		},

		// 将字符串解析为一个浮点数
		// 
		// Syntax: myString.toFloat();
		// 
		// Arguments: N/A
		// 
		// Returns: 
		//	(number) 浮点数. 
		//	(NaN) 如果字符串内容不是数值, 则返回 NaN 
		// 
		// Examples: 
		//	'95.25%'.toFloat(); // 返回 95.25
		//	'10.848'.toFloat(); // 返回 10.848
		toFloat: function () {
			return parseFloat(this);
		},

		// 将代表十六进制颜色代码的字符串转换成RGB格式的颜色代码. 
		// 字符串的颜色格式必须是如下格式的(可以不带前缀的#):'#ffffff', #fff', 'ffffff', 或 'fff'.
		// 
		// Syntax: myString.hexToRgb([array]);
		// 
		// Arguments: 
		//	array - (boolean, 可选) 如果为true, 则输出为一个数组形式, 而不是通常的字符串形式
		// 
		// Returns: 
		//	(string) RGB格式的颜色代码字符串. 
		//	(array) 如果设置了array为true, 则返回数组形式的RGB颜色代码
		// 
		// Examples: 
		//	'#123'.hexToRgb(); // 返回 'rgb(17, 34, 51)'
		//	'112233'.hexToRgb(); // 返回 'rgb(17, 34, 51)'
		//	'#112233'.hexToRgb(true); // 返回 [17, 34, 51]
		hexToRgb: function (array) {
			// 这里假设输入'#ffffff'，经过match方法之后被打散为一个数组['#ffffff','ff','ff'.'ff']
			var hex = String(this).match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);
			// 去除这个数组的第一个元素然后调用之前Array扩展的hexToRgb转化为rgb(255,255,255)
			// 或者[255,255,255]如果传入的array参数为true的话
			return (hex) ? hex.slice(1).hexToRgb(array) : null;
		},

		// 将代表RGB格式的颜色代码的字符串转换成十六进制颜色代码. 
		// 字符串的RGB颜色格式必须是如下格式:"rgb(255,255,255)", 或 "rgba(255,255,255,1)"
		// 
		// Syntax: myString.rgbToHex([array]);
		// 
		// Arguments: 
		//	array - (boolean, 可选) 如果为true, 则输出为一个数组形式(如： ['ff','33','00']), 而不是通常的字符串形式(如: "#ff3300")
		// 
		// Returns: 
		//	(string) 十六进制的颜色代码字符串; 或者, 如果RGB代码设置了第四个值(alpha)为0, 则返回'transparent' 
		//	(array) 如果设置了array为true, 则返回数组形式的十六进制颜色代码
		// 
		// Examples: 
		//	'rgb(17, 34, 51)'.rgbToHex(); // 返回 '#112233'
		//	'rgb(17, 34, 51)'.rgbToHex(true); // 返回 ['11', '22', '33']
		//	'rgba(17, 34, 51, 0)'.rgbToHex(); // 返回 'transparent'
		/**
		* 在这里复习下Regexp对象以及String的与正则匹配相关的方法
		* 在正则表达式带有g全局符号时str.match返回一个数组包含满足正则表达式的
		* 子字符串，如果不包含g全局符号。只返回包含第一个满足的子字符串的单元素数组对象
		* 不过这个数组包含一些额外信息，比如这个字符串在源字符串的index等等，用array.index查看
		* RegExp的exec比String的match还要复杂一些，当不带全局符号时exec与match完全一致
		* 返回的数组0为匹配字符串， 1 ，2....为其余顺序子匹配，这个数组还有index和input即测试字符串
		* 当有g全局符号时，match如上所说只返回一个数组，返回匹配整条reg的字符串，但是无任何其他如index子匹配等信息
		* 当有g全局符号时，exec永远只返回第一个匹配
		**/
		rgbToHex: function (array) {
			// 将"rgb(255,255,255)"中的数组提取出来(注意全局符号)，形成数组[255,255,255]
			var rgb = String(this).match(/\d{1,3}/g);
			// 调用数组的rgbToHex
			return (rgb) ? rgb.rgbToHex(array) : null;
		},

		// 对字符串中给出的替换标记进行值替换(类似简单模板). 清除未定义的关键字和, 忽略多余的关键字
		// 
		// Syntax: myString.substitute(object[, regexp]);
		// 
		// Arguments: 
		//	object - (mixed) 用于对字符串进行替换填充的对象. 
		//	regexp - (regexp, 可选) 自定义替换的正则表达式模式(需要带有g参数). 默认值: /\?{([^}]+)}/g (即替换大括号标识的区域). 
		// 
		// Returns: 
		//	(string) - 替换后的字符串
		// 
		// Examples: 
		//	var myString = '{subject} is {property_1} and {property_2}.';
		//	var myObject = {subject: 'Jack Bauer', property_1: 'our lord', property_2: 'saviour'};
		//	myString.substitute(myObject); // 返回 'Jack Bauer is our lord and saviour'
		substitute: function (object, regexp) {
			//   /\\?\{([^{}]+)\}/g  默认模板标记是{}以及它包裹的字符串如{subs}
			return String(this).replace(regexp || (/\\?\{([^{}]+)\}/g), function (match, name) {
				if (match.charAt(0) == '\\') {
					return match.slice(1);
				}
				return (object[name] != null) ? object[name] : '';
			});
		}

	});

	// #endregion

	// #region - Number -

	/*
	---

	name: Number

	description: Contains Number Prototypes like limit, round, times, and ceil.

	license: MIT-style license.

	requires: Type

	provides: Number

	...
	*/

	Number.implement({

		// 将取值范围限制在指定区间(在区间内,取原值;超出区间,则取邻近的区间边界值)
		// 
		// Syntax: myNumber.limit(min, max);
		// 
		// Arguments: 
		//	min - (number) The minimum possible value. 
		//	max - (number) The maximum possible value.
		// 
		// Returns: 
		//	(number) 在区间内取出的值
		// 
		// Examples: 
		//	(12).limit(2, 6.5);  // returns 6.5
		//	(-4).limit(2, 6.5);  // returns 2
		//	(4.3).limit(2, 6.5); // returns 4.3
		limit: function (min, max) {
			return Math.min(max, Math.max(min, this));
		},

		// 对数值进行指定位上的四舍五入
		// 
		// Syntax: myNumber.round([precision]);
		// 
		// Arguments: 
		//	precision - (number, 可选: 默认为0) 数值的精度
		// 
		// Returns: 
		//	(number) 四舍五入后的值
		// 
		// Examples: 
		//	(12.45).round()   // returns 12
		//	(12.45).round(1)  // returns 12.5
		//	(12.45).round(-1) // returns 10
		//
		// 提示：
		// 参数可以为负数
		round: function (precision) {
			precision = Math.pow(10, precision || 0).toFixed(precision < 0 ? -precision : 0);
			return Math.round(this * precision) / precision;
		},

		// 以本数值表示的次数进行迭代
		// 
		// Syntax: myNumber.times(fn[, bind]);
		// 
		// Arguments: 
		//	fn - (function) The function which should be executed on each iteration of the loop. This function is passed the current iteration's index.
		//									作用于迭代项的函数. 当前迭代值将作为参数传入该函数 
		//	bind - (object, 可选) The object to use as 'this' in the function. For more information see 函数:bind. 
		//												"this"所引用的对象, 详情请参考Function:bind.
		// 
		// Returns: N/A
		// 
		// Examples: 
		// (4).times(alert); // alerts "0", then "1", then "2", then "3".
		times: function (fn, bind) {
			for (var i = 0; i < this; i++) {
				fn.call(bind, i, this);
			}
		},

		// 将数值转换成浮点数
		// 
		// Syntax: myNumber.toFloat();
		// 
		// Arguments: N/A
		// 
		// Returns: 
		//	(number) The number as a float
		// 
		// Examples: 
		//	(111).toFloat(); // returns 111
		//	(111.1).toFloat(); // returns 111.1
		toFloat: function () {
			return parseFloat(this);
		},

		// 将数值以指定进制为基准进行计算转换为十进制整数
		// 
		// Syntax: myNumber.toInt([base]);
		// 
		// Arguments: 
		//	base - (number, optional: defaults to 10) The base to use
		// 
		// Returns: 
		//	(number) A number with the base provided
		// 
		// Examples: 
		//	(111).toInt(); // returns 111
		//	(111.1).toInt(); // returns 111
		//	(111).toInt(2); // returns 7 (111代表二进制7)
		toInt: function (base) {
			return parseInt(this, base || 10);
		}

	});

	// 将times方法取个别名 each
	Number.alias('each', 'times');

	/**
	* 将列出的本属于Math的静态方法转嫁到Number的原型对象上
	* 比如Math.cos(2)可以直接使用 2.cos();来代替
	**/
	(function (math) {
		var methods = {};
		math.each(function (name) {
			if (!Number[name]) methods[name] = function () {
				// concat用来连接两个数组
				return Math[name].apply(null, [this].concat(Array.from(arguments)));
			};
		});
		Number.implement(methods);
	})(['abs', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'exp', 'floor', 'log', 'max', 'min', 'pow', 'sin', 'sqrt', 'tan']);

	// #endregion

	// #region - Function -

	/*
	---

	name: Function

	description: Contains Function Prototypes like create, bind, pass, and delay.

	license: MIT-style license.

	requires: Type

	provides: Function

	...
	*/

	Function.extend({

		// Tries to execute a number of functions. Returns immediately the return value of the first non-failed function without executing successive functions, or null
		// 
		// Syntax: Function.attempt(fn[, fn, fn, fn, ...]);
		// 
		// Arguments: 
		//	fn - (function) Any number of functions to execute
		// 
		// Returns: 
		//	(mixed) Standard return of the called function. 
		//	(null) null if all the passed functions fail.
		// 
		// Examples: 
		//	var result = Function.attempt(function(){
		//		return some.made.up.object;
		//	}, function(){
		//		return jibberish.that.doesnt.exists;
		//	}, function(){
		//		return false;
		//	});
		//	 
		//	//result is false
		//	 
		//	var failure, success;
		//	 
		//	Function.attempt(function(){
		//		some.made.up.object = 'something';
		//		success = true;
		//	}, function(){
		//		failure = true;
		//	});
		//	 
		//	if (success) alert('yey!');
		/**
		* Function在扩展其原型对象时，之前首先扩展了一个静态方法attempt，它在传入的众多函数中返回第一个可以运行
		* 的函数的返回值这通常用于方法的延后设定。比如一些浏览器相关的方法。具体应用在Browser中有，因为一些需要
		* 用户浏览器检测结果来返回不同值的函数，但实际情况是用户浏览器只需要一次检测，所以可以直接对这个方法进行
		* 设置来返回固定浏览器相关的返回值，比如下面Browser部分中的Request中就有很好的应用。
		**/
		attempt: function () {
			/**
			# 苦苦的苦瓜 
			# 2011-10-12
			# for循环改为while循环
			# for (var i = 0, l = arguments.length; i < l; i++) {
			**/
			var i = 0, l = arguments.length;
			while (i < l) {
				// 尝试运行所有传入的函数，返回第一个成功运行的函数返回值
				try {
					return arguments[i++]();
				} catch (e) { }
			}
			return null;
		}

	});

	/**
	* 接下开始正式的原型扩展，Function的原型扩展非常重要，因为所有的类(亦称之为构造函数)都可以使用这些扩展的函数，
	* 包括Object！！！它这里的扩展基本是完成对原函数的增强，即返回另外一个基于原函数但作了一定处理的新函数。
	* 具体如下：
	**/
	Function.implement({

		// Tries to execute a single function. Returns immediately the return value of the function if it does not fail, or null. 尝试执行闭包函数
		// 
		// Syntax: var myFunctionResult = myFunction.attempt(args[, bind]);
		// 
		// Arguments: 
		//	args - (mixed) An argument, or array of arguments to run the function with. 传递给闭包函数的参数(如果是多个参数,必须使用数组)
		//	bind - (object, 可选) The object that the "this" of the function will refer to 闭包函数中"this"引用的对象
		// 
		// Returns: 
		//	(mixed) This Function's return value. 
		//	(null) null if the function fails. 
		//	(mixed) 执行后的返回结果;如果执行出错,返回null
		// 
		// Examples: 
		//	var myFunction = function(){
		//		return some.made.up.object;
		//	};
		//	myFunction.attempt(); // returns 'null'
		//	
		//	var myFunction = function(val){
		//		return val;
		//	};
		//	myFunction.attempt(false); // returns 'false'
		attempt: function (args, bind) {
			try {
				return this.apply(bind, Array.from(args));
			} catch (e) { }

			return null;
		},

		// #region -- !ES5-bind --

		// Changes the scope of this within the target function to refer to the bind parameter
		// 将函数的this指针绑定到某个对象上，也可以预先绑定部分参数
		// 比如 func.bind(obj,2,3)(4)就相当于 func.apply(obj,[2,3,4]);
		// 
		// Syntax: myFunction.bind([bind[, args]]);
		// 
		// Arguments: 
		//	bind - (object, 可选) The object that the "this" of the function will refer to.(函数中"this"引用的对象)
		//	args - (mixed, 可选) The arguments to pass to the function (must be an array if passing more than one argument).(传递给函数的参数(如果是多个参数,必须使用数组))
		//					这个注释应该是错误的，多个参数不能使用数组
		// 
		// Returns: 
		//	(function) The bound function.(重新绑定后的函数)
		// 
		// Examples: 
		//	function myFunction(){
		//		//Note that 'this' here refers to window, not an element.
		//		// the function must be bound to the element we want to manipulate.
		//		this.setStyle('color', 'red');
		//	};
		//	
		//	var myBoundFunction = myFunction.bind(myElement);
		//	myBoundFunction(); // makes myElement's text red
		bind: function (that) {
			// 缓存函数的this指针，这一步通常在存在需要利用到外围函数的this对象的
			// 内部函数时，这是必须的
			var self = this,
			// 如果参数数量大于1，则去除bind之后的所有元素组成一个数组
					args = arguments.length > 1 ? Array.slice(arguments, 1) : null,
			F = function () { };

			// 这里是与下面pass函数的主要区别，即args.concat(Array.from(arguments))
			// 这个语句将连接预先绑定的参数，和后面运行函数所输入的参数
			var bound = function () {
				var context = that, length = arguments.length;
				if (this instanceof bound) {
					F.prototype = self.prototype;
					context = new F;
				}
				var result = (!args && !length)
						? self.call(context)
						: self.apply(context, args && length ? args.concat(Array.slice(arguments)) : args || arguments);
				return context == that ? result : context;
			};
			return bound;
		},

		// #endregion !ES5-bind

		// Returns a closure with arguments and bind(返回指定了携带参数和绑定this对象的闭包函数)
		// bind的简化版两者都可以预绑参数和this对象. 区别就是这个函数注重预绑参数，bind注重预绑this对象。
		// 并且pass方法所返回的闭包函数无法连接绑定的参数和输入的参数,
		// 
		// Syntax: var newFunction = myFunction.pass([args[, bind]]);
		// 
		// Arguments: 
		//	args - (mixed, 可选) The arguments to pass to the function (must be an array if passing more than one argument).(传递给闭包函数的参数(如果是多个参数,必须使用数组))
		//	bind - (object, 可选) The object that the "this" of the function will refer to.(闭包函数中"this"引用的对象)
		// 
		// Returns: 
		//	(function) The function whose arguments are passed when called.(生成的闭包函数)
		// 
		// Examples: 
		//	var myFunction = function(){
		//		var result = 'Passed: ';
		//		for (var i = 0, l = arguments.length; i < l; i++){
		//			result += (arguments[i] + ' ');
		//		}
		//		return result;
		//	}
		//	var myHello = myFunction.pass('hello');
		//	var myItems = myFunction.pass(['peach', 'apple', 'orange']);
		//	 
		//	//Later in the code, the functions can be executed:
		//	alert(myHello()); // passes 'hello' to myFunction.
		//	alert(myItems()); // passes the array of items to myFunction.
		pass: function (args, bind) {
			var self = this;
			if (args != null) { args = Array.from(args); }
			return function () {
				return self.apply(bind, args || arguments);
			};
		},

		// Delays the execution of a function by a specified duration
		// 
		// Syntax: var timeoutID = myFunction.delay(delay[, bind[, args]]);
		// 
		// Arguments: 
		//	delay - (number) The duration to wait (in milliseconds).(延迟毫秒数)
		//	bind - (object, optional) The object that the "this" of the function will refer to.(函数对象中"this"引用的对象)
		//	args - (mixed, optional) The arguments passed (must be an array if the arguments are greater than one).(传递给函数的参数(如果是多个参数,必须使用数组))
		// 
		// Returns: 
		//	(number) The JavaScript timeout id (for clearing delays)(定时器引用(用于清除这个定时器时使用))
		// 
		// Examples: 
		//	var myFunction = function(){ alert('moo! Element id is: ' + this.id); };
		//	 
		//	//wait 50 milliseconds, then call myFunction and bind myElement to it
		//	myFunction.delay(50, myElement); // alerts: 'moo! Element id is: ... '
		//	
		//	//an anonymous function which waits a second and then alerts
		//	(function(){ alert('one second later...'); }).delay(1000);
		//	
		//	//to stop the delay, clearTimeout can be used like so:
		//	var timer = myFunction.delay(50);
		//	clearTimeout(timer);
		/**
		* 即setTimeout，pass方法的妙用可见一斑。
		* 一、用来绑定this对象
		* 二、本身pass方法返回的闭包函数在无参数的时候其实是绑定了需要的参数的
		* 稍微了解下js定时器语法的都知道，不优雅就算了，简直就是丑陋
		* func.delay();相比原生的setTimeout 语法的使用上应该也容易很多
		**/
		delay: function (delay, bind, args) {
			return setTimeout(this.pass((args == null ? [] : args), bind), delay);
		},

		// Executes a function in the specified intervals of time. Periodic execution can be stopped using the clearInterval function
		// 
		// Syntax: var intervalID = myFunction.periodical(period[, bind[, args]]);
		// 
		// Arguments: 
		//	period - (number) The duration of the intervals between executions.(间隔毫秒数)
		//	bind - (object, optional) The object that the "this" of the function will refer to.(函数对象中"this"所引用的对象)
		//	args - (mixed, optional) The arguments passed (must be an array if the arguments are greater than one).(传递给闭包的参数(如果是多个参数,必须使用数组))
		// 
		// Returns: 
		//	(number) The Interval id (for clearing a periodical)(定时器引用(用于清除这个定时器时使用))
		// 
		// Examples: 
		//	var Site = { counter: 0 };
		//	var addCount = function(){ this.counter++; };
		//	addCount.periodical(1000, Site); //adds the number of seconds at the Site.
		//	
		//	// the interval can be stopped using the clearInterval function
		//	var timer = myFunction.periodical(1000);
		//	clearInterval(timer);
		periodical: function (periodical, bind, args) {
			return setInterval(this.pass((args == null ? [] : args), bind), periodical);
		}

	});

	// #endregion

	// #region - Object, Object.Extras -

	(function () {

		var defined = function (value) {
			return value != null;
		};

		var hasOwnProperty = Object.prototype.hasOwnProperty;

		Object.extend({

			// #region Object

			/*
			---

			name: Object

			description: Object generic methods

			license: MIT-style license.

			requires: Type

			provides: [Object, Hash]

			由于不能对Object的原型做直接扩展，这里针对Object的静态扩展基本是将1.2的Hash对象的实例方法全部转移了过来
			(1.3将Hash对象放入了More包)，所以这里的一切扩展可以视为是服务于Hash型数组(也可称之为字面量对象，
			或者纯洁的对象)。由于是静态方法，所以必须传入要处理的object，这里的所有扩展的第一个参数object都可以视为
			一个纯洁的object(由对象字面量产生的)

			...
			*/

			// Get a subset of an object.(获得一个对象的子集)
			// 
			// Syntax: Object.subset(object, keys);
			// 
			// Arguments: 
			//	object - (object) 源对象 
			//	keys - (array) 键值数组
			// 
			// Returns: 
			//	(object) 对象的子集
			// 
			// Examples: 
			//	var object = {
			//		a: 'one',
			//		b: 'two',
			//		c: 'three'
			//	};
			//	Object.subset(object, ['a', 'c']); // returns {a: 'one', c: 'three'}
			subset: function (object, keys) {
				var results = {};
				/**
				# 苦苦的苦瓜 
				# 2011-10-12
				# for循环改为while循环
				# for (var i = 0, l = keys.length; i < l; i++) {
				**/
				var i = 0, l = keys.length;
				while (i < l) {
					var k = keys[i++];
					if (k in object) {
						results[k] = object[k];
					}
				}
				return results;
			},

			// Creates a new map with the results of calling a provided function on every value in the map
			// 对对象中的每个键值对进行迭代,并通过指定函数处理后重新映射成一个新的对象
			// 
			// Syntax: var mappedObject = Object.map(object, fn[, bind]);
			// 
			// Arguments: 
			//	object - (object) 源对象 
			//	fn - (function) 处理每个迭代键值对的函数 
			//		Syntax: fn(value, key, object)
			//		Arguments: 
			//			value - (mixed) 当前迭代值 
			//			key - (string) 当前迭代键 
			//			object - (object) 主调对象 
			//	bind - (object, 可选) 函数中'this'引用的对象. 详见 Function:bind. 
			// 
			// Returns: 
			//	(object) 重新映射后的新对象
			// 
			// Examples: 
			//	var myObject = {a: 1, b: 2, c: 3};
			//	var timesTwo = Object.map(myObject, function(value, key){
			//		return value * 2;
			//	}); // timesTwo now holds an object containing: {a: 2, b: 4, c: 6};
			map: function (object, fn, bind) {
				var results = {};
				for (var key in object) {
					// object.hasOwnProperty(key)的意思是此属性来自于自身定义而非prototype
					if (hasOwnProperty.call(object, key)) {
						results[key] = fn.call(bind, object[key], key, object);
					}
				}
				return results;
			},

			// Creates a new object with all of the elements of the object for which the provided filtering function returns true.
			// 过滤对象中的键值对, 并将通过过滤的键值对组成一个新的对象
			// 
			// Syntax: var filteredObject = Object.filter(object, fn[, bind]);
			// 
			// Arguments: 
			//	object - (object) 源对象 
			//	fn - (function) 处理每个迭代键值对的函数 
			//		Syntax: fn(value, key, object)
			//		Arguments: 
			//			value - (mixed) 当前迭代值 
			//			key - (string) 当前迭代键 
			//			object - (object) 主调对象 
			//	bind - (object, 可选) 函数中'this'引用的对象. 详见 Function:bind. 
			// 
			// Returns: 
			//	(object) 过滤后的新对象
			// 
			// Examples: 
			//	var myObject = {a: 10, b: 20, c: 30};
			//	var biggerThanTwenty = Object.filter(myObject, function(value, key){
			//		return value > 20;
			//	}); // biggerThanTwenty now holds an object containing: {c: 30}
			filter: function (object, fn, bind) {
				var results = {};
				for (var key in object) {
					var value = object[key];
					if (hasOwnProperty.call(object, key) && fn.call(bind, value, key, object)) {
						results[key] = value;
					}
				}
				return results;
			},

			// Returns true if every value in the object satisfies the provided testing function.
			// 迭代对象中的每个键值对, 如果每个迭代项都通过测试函数的测试, 则返回true
			// 
			// Syntax: var allPassed = Object.every(object, fn[, bind]);
			// 
			// Arguments: 
			//	object - (object) 源对象 
			//	fn - (function) 处理每个迭代键值对的函数 
			//		Syntax: fn(value, key, object)
			//		Arguments: 
			//			value - (mixed) 当前迭代值 
			//			key - (string) 当前迭代键 
			//			object - (object) 主调对象 
			//	bind - (object, 可选) 函数中'this'引用的对象. 详见 Function:bind. 
			// 
			// Returns: 
			// (boolean) 如果每个键值对都通过测试函数的测试, 则返回 true ; 否则返回 false 
			// 
			// Examples: 
			//	var myObject = {a: 10, b: 4, c: 25, d: 100};
			//	var areAllBigEnough = Object.every(myObject, function(value, key){
			//		return value > 20;
			//	}); // areAllBigEnough = false
			every: function (object, fn, bind) {
				for (var key in object) {
					if (hasOwnProperty.call(object, key) && !fn.call(bind, object[key], key)) {
						return false;
					}
				}
				return true;
			},

			// Returns true if at least one value in the object satisfies the provided testing function
			// 
			// Syntax: var anyPassed = Object.some(object, fn[, bind]);
			// 
			// Arguments: 
			//	object - (object) 源对象 
			//	fn - (function) 处理每个迭代键值对的函数 
			//		Syntax: fn(value, key, object)
			//		Arguments: 
			//			value - (mixed) 当前迭代值 
			//			key - (string) 当前迭代键 
			//			object - (object) 主调对象 
			//	bind - (object, 可选) 函数中'this'引用的对象. 详见 Function:bind. 
			// 
			// Returns: 
			//	(boolean) If any value in the object satisfies the provided testing function, returns true. Otherwise, returns false
			// 
			// Examples: 
			//	var myObject = {a: 10, b: 4, c: 25, d: 100};
			//	var isAnyBigEnough = Object.some(myObject, function(value, key){
			//		return value > 20;
			//	}); //isAnyBigEnough = true
			some: function (object, fn, bind) {
				for (var key in object) {
					if (hasOwnProperty.call(object, key) && fn.call(bind, object[key], key)) {
						return true;
					}
				}
				return false;
			},

			// Returns an array containing all the keys, in the same order as the values returned by Object:values.
			// 返回object的所有key组成的数组，即键数组
			// 
			// Syntax: var keys = Object.keys(object);
			// 
			// Arguments: 
			//	object - (object) The object.
			// 
			// Returns: 
			//	(array) An array containing all the keys of the object.
			// 
			// Examples: 
			// 
			keys: function (object) {
				var keys = [];
				for (var key in object) {
					if (hasOwnProperty.call(object, key)) {
						keys.push(key);
					}
				}
				return keys;
			},

			// Returns an array containing all the values, in the same order as the keys returned by Object:keys.
			// 返回object的所有value组成的数组，即值数组
			// 
			// Syntax: var values = Object.values(object);
			// 
			// Arguments: 
			//	object - (object) The object.
			// 
			// Returns: 
			//	(array) An array containing all the values of the object.
			// 
			// Examples: 
			// 
			values: function (object) {
				var values = [];
				for (var key in object) {
					if (hasOwnProperty.call(object, key)) {
						values.push(object[key]);
					}
				}
				return values;
			},

			// Returns the number of keys in the object.
			// 获得object键值对的数量
			// 
			// Syntax: var length = Object.getLength(object);
			// 
			// Arguments: 
			//	object - (object) The object.
			// 
			// Returns: 
			//	(number) The length of the object.
			// 
			// Examples: 
			//	var myObject = {
			//		name: 'John',
			//		lastName: 'Doe'
			//	});
			//	Object.getLength(myObject); // returns 2
			getLength: function (object) {
				return Object.keys(object).length;
			},

			// Returns the key of the specified value. Synonymous with Array:indexOf.
			// 返回某个值在object的键名
			// 
			// Syntax: var key = Object.keyOf(object, item);
			// 
			// Arguments: 
			//	object - (object) The object.
			//	item - (mixed) The item to search for in the object.
			// 
			// Returns: 
			//	(string) If the object has a the specified item in it, returns the key of that item.
			//	(boolean) Otherwise, returns false.
			// 
			// Examples: 
			//	var myObject = {a: 'one', b: 'two', c: 3};
			//	Object.keyOf(myObject, 'two'); // returns 'b'
			//	Object.keyOf(myObject, 3); // returns 'c'
			//	Object.keyOf(myObject, 'four'); // returns false
			keyOf: function (object, value) {
				for (var key in object) {
					if (hasOwnProperty.call(object, key) && object[key] === value) {
						return key;
					}
				}
				return null;
			},

			// Tests for the presence of a specified value in the object.
			// 确定是否包含某个值
			// 
			// Syntax: var inObject = Object.contains(object, value);
			// 
			// Arguments: 
			//	object - (object) The object.
			//	value - (mixed) The value to search for in the Object.
			// 
			// Returns: 
			//	(boolean) If the object has the passed in value in any of the keys, returns true. Otherwise, returns false.
			// 
			// Examples: 
			//	var myObject = {a: 'one', b: 'two', c: 'three'};
			//	Object.contains(myObject, 'one'); // returns true
			//	Object.contains(myObject, 'four'); // returns false
			contains: function (object, value) {
				return Object.keyOf(object, value) != null;
			},

			// Generates a query string from key/value pairs in an object and URI encodes the values
			// 
			// Syntax: var queryString = Object.toQueryString(object[, base]);
			// 
			// Arguments: 
			//	object - (object) The object to generate the query string from.
			//	base - (string, optional) Will be used as base variable in the query string.
			// 
			// Returns: 
			//	(string) The query string.
			// 
			// Examples: 
			//	Object.toQueryString({apple: 'red', lemon: 'yellow'}); // returns 'apple=red&lemon=yellow'
			//	Object.toQueryString({apple: 'red', lemon: 'yellow'}, 'fruits'); // returns 'fruits[apple]=red&fruits[lemon]=yellow'
			/**
			* 将这个object的所有键值对转化为一个字符串
			* {key1:value1, key2 : value2 , key3: value3}转化为
			* 'key1=value1&key2=value2&key3=value3'
			* 每个value都要进行URI编码==>encodeURIComponent(value)
			**/
			toQueryString: function (object, base) {
				// 先顶一个临时数组，来存放需要连接的子字符串
				var queryString = [];

				Object.each(object, function (value, key) {
					if (base) {
						key = base + '[' + key + ']';
					}
					var result;
					switch (typeOf(value)) {
						case 'object':
							// 这种是自迭代的一种常用的方式
							result = Object.toQueryString(value, key);
							break;

						case 'array':
							var qs = {};
							// 如果是array就转变为Hash数组，键值即为原来的数组下标
							value.each(function (val, i) {
								qs[i] = val;
							});
							result = Object.toQueryString(qs, key);
							break;

						default:
							// 无论深度多少，最终都会迭代到这最基础的一步，即最终的结果都是由这一分支归并而来
							result = key + '=' + encodeURIComponent(value);
					}
					if (value != null) { queryString.push(result); }
				});

				return queryString.join('&');
			},

			// #endregion

			// #region Object.Extras

			/*
			---

			script: Object.Extras.js

			name: Object.Extras

			description: Extra Object generics, like getFromPath which allows a path notation to child elements.

			license: MIT-style license

			authors:
			- Aaron Newton

			requires:
			- Core/Object
			- /MooTools.More

			provides: [Object.Extras]

			...
			*/

			// Returns a value of an object by its pat
			// 
			// Syntax: Object.getFromPath(myObject, path);
			// 
			// Arguments: 
			//	object - (object) The object to search in
			//	path - (string, array) the path to the key for the value you wish to retrieve
			// 
			// Returns: 
			//	(null or mixed) if the path has no value, null is returned; otherwise the value that corresponds to the path is returned.
			// 
			// Examples: 
			//	Object.getFromPath({
			//		food: {
			//			fruits: {
			//				apples: "red",
			//				lemon: "yellow"
			//			}
			//		}
			//	}, 'food.fruits.apples'); // 'red'
			//	
			//	Object.getFromPath({food: {pizza: 'yum!!'}}, ['food', 'pizza']); // 'yum!!'
			getFromPath: function (source, parts) {
				if (typeof parts == 'string') {
					parts = parts.split('.');
				}
				for (var i = 0, l = parts.length; i < l; i++) {
					if (hasOwnProperty.call(source, parts[i])) {
						source = source[parts[i]];
					} else {
						return null;
					}
				}
				return source;
			},

			// Removes values from the object
			// 
			// Syntax: Object.cleanValues(myObject, method);
			// 
			// Arguments: 
			//	object - (object) The original object that should be cleaned up
			//	method - (function) The function that each value in the Hash is passed. If it returns true the value is kept. Defaults to check if the value != null.
			// 
			// Returns: 
			//	(object) - The cleaned object
			// 
			// Examples: 
			//	Object.cleanValues({
			//		foo: 'bar',
			//		something: 'else',
			//		missing: null
			//	});
			//	
			//	//remove all values < 0
			//	Object.cleanValues({
			//		a: -1,
			//		b: 2,
			//		c: 0,
			//		d: -5
			//	}, function(value){
			//		if (typeOf(value) != "number") return true;
			//		return value > 0;
			//	});
			cleanValues: function (object, method) {
				method = method || defined;
				for (var key in object) {
					if (!method(object[key])) {
						delete object[key];
					}
				}
				return object;
			},

			// Deletes a property from the object.
			// 
			// Syntax: Object.erase(object, key)
			// 
			// Arguments: N/A
			// 
			// Returns: 
			//	(object) - The object.
			// 
			// Examples: 
			//	var alphabet = {a: 'a', b: 'b', c: 'c'};
			//	Object.erase(alphabet, 'b'); // alphabet == {a: 'a', c: 'c'};
			erase: function (object, key) {
				if (hasOwnProperty.call(object, key)) {
					delete object[key];
				}
				return object;
			},

			// Runs all the methods that are values of the object while passing any additional arguments passed to this function.
			// 
			// Syntax: Object.run(object[, arg1[, arg2[, ...]]])
			// 
			// Arguments: N/A
			// 
			// Returns: 
			//	(object) - The object.
			// 
			// Examples: 
			//	var initMyPage = {
			//		setupNav: function(){
			//			//set up the nav
			//		},
			//		setupSearch: function(){
			//			//set up the search
			//		}
			//	};
			//	 
			//	window.addEvent('domready', function(){
			//		Object.run(initMyPage);
			//	});
			run: function (object) {
				var args = Array.slice(arguments, 1);
				for (var key in object) {
					if (object[key].apply) {
						object[key].apply(object, args);
					}
				}
				return object;
			}

			// #endregion

		});

	})();

	// #endregion

	// #region - Array.Extras -

	/*
	---

	script: Array.Extras.js

	name: Array.Extras

	description: Extends the Array native object to include useful methods to work with arrays.

	license: MIT-style license

	authors:
	- Christoph Pojer
	- Sebastian Markbåge

	requires:
	- Core/Array
	- MooTools.More

	provides: [Array.Extras]

	...
	*/

	(function (nil) {

		Array.implement({

			// Calls Math.min on the array and returns its lowest value.
			// 
			// Syntax: myArray.min();
			// 
			// Arguments: N/A
			// 
			// Returns: 
			//	(number) the lowest number in the array
			// 
			// Examples: 
			// [1, 2, 3].min(); //returns 1
			min: function () {
				return Math.min.apply(null, this);
			},

			// Calls Math.max on the array and returns its highest value.
			// 
			// Syntax: myArray.max();
			// 
			// Arguments: N/A
			// 
			// Returns: 
			//	(number) the highest number in the array
			// 
			// Examples: 
			// [1, 2, 3].max(); //returns 3
			max: function () {
				return Math.max.apply(null, this);
			},

			// Calculates the average value of the array.
			// 
			// Syntax: myArray.average();
			// 
			// Arguments: N/A
			// 
			// Returns: 
			//	(number) the average value of the array
			// 
			// Examples: 
			// [1, 2, 3].average(); //returns 2
			average: function () {
				return this.length ? this.sum() / this.length : 0;
			},

			// Sums up all values in an array.
			// 
			// Syntax: myArray.sum();
			// 
			// Arguments: N/A
			// 
			// Returns: 
			//	(number) a number containing the sum of all values in the given array
			// 
			// Examples: 
			// $$('ul.menu li').getWidth().sum();	//returns the width of all li elements inside ul.menu as a sum
			sum: function () {
				var result = 0, l = this.length;
				if (l) {
					while (l--) { result += this[l]; }
				}
				return result;
			},

			// Returns a new array without duplicate values
			// 
			// Syntax: myArrayWithoutDupes = myArray.unique();
			// 
			// Arguments: N/A
			// 
			// Returns: 
			//	(array) a new array without duplicates.
			// 
			// Examples: 
			// var fruits = ['apple', 'lemon', 'pear', 'lemon', 'apple'].unique();	//fruits == ['apple', 'lemon', 'pear']
			unique: function () {
				return [].combine(this);
			},

			// Randomizes the array (altering it).
			// 
			// Syntax: myArray.shuffle();
			// 
			// Arguments: N/A
			// 
			// Returns: 
			//	(array) the array.
			// 
			// Examples: 
			// [1, 2, 3].shuffle();
			shuffle: function () {
				for (var i = this.length; i && --i; ) {
					var temp = this[i], r = Math.floor(Math.random() * (i + 1));
					this[i] = this[r];
					this[r] = temp;
				}
				return this;
			},

			// Apply a function against an accumulator and each value of the array (from left-to-right) as to reduce it to a single value.
			// 
			// Syntax: result = myArray.reduce(fn[, value]);
			// 
			// Arguments: 
			//	fn - (function) Function to execute on each value in the array.
			//	value - (mixed) Value to use as the first argument to the first call of the fn
			// 
			//	Signature: fn(previousValue, currentValue, index, array)
			// 
			// Returns: 
			//	(mixed) Returns the reduced single value of the array
			// 
			// Examples: 
			//	[0, 1, 2, 3, 4].reduce(function(a, b){
			//		return a + b;
			//	}); // returns 10
			//	 
			//	[0, 1, 2, 3, 4].reduce(function(a, b){
			//		return a + b;
			//	}, 20); // returns 30
			reduce: function (fn, value) {
				for (var i = 0, l = this.length; i < l; i++) {
					if (i in this) {
						value = value === nil ? this[i] : fn.call(null, value, this[i], i, this);
					}
				}
				return value;
			},

			// Apply a function simultaneously against two values of the array (from right-to-left) as to reduce it to a single value.
			// 
			// Syntax: result = myArray.reduceRight(fn[, value]);
			// 
			// Arguments: 
			//	fn - (function) Function to execute on each value in the array.
			//	value - (mixed) Value to use as the first argument to the first call of the fn
			// 
			//	Signature: fn(previousValue, currentValue, index, array)
			// 
			// Returns: 
			//	(mixed) Returns the reduced single value of the array.
			// 
			// Examples: 
			//	var flattened = [[0, 1], [2, 3], [4, 5]].reduceRight(function(a, b) {
			//		return a.concat(b);
			//	}, []);	// flattened is [4, 5, 2, 3, 0, 1]
			reduceRight: function (fn, value) {
				var i = this.length;
				while (i--) {
					if (i in this) {
						value = value === nil ? this[i] : fn.call(null, value, this[i], i, this);
					}
				}
				return value;
			}

		});

	})();

	// #endregion

	// #region - String.Extras -

	/*
	---

	script: String.Extras.js

	name: String.Extras

	description: Extends the String native object to include methods useful in managing various kinds of strings (query strings, urls, html, etc).

	license: MIT-style license

	authors:
	- Aaron Newton
	- Guillermo Rauch
	- Christopher Pitt

	requires:
	- Core/String
	- Core/Array
	- MooTools.More

	provides: [String.Extras]

	...
	*/

	(function () {

		var special = {
			'a': /[àáâãäåăą]/g,
			'A': /[ÀÁÂÃÄÅĂĄ]/g,
			'c': /[ćčç]/g,
			'C': /[ĆČÇ]/g,
			'd': /[ďđ]/g,
			'D': /[ĎÐ]/g,
			'e': /[èéêëěę]/g,
			'E': /[ÈÉÊËĚĘ]/g,
			'g': /[ğ]/g,
			'G': /[Ğ]/g,
			'i': /[ìíîï]/g,
			'I': /[ÌÍÎÏ]/g,
			'l': /[ĺľł]/g,
			'L': /[ĹĽŁ]/g,
			'n': /[ñňń]/g,
			'N': /[ÑŇŃ]/g,
			'o': /[òóôõöøő]/g,
			'O': /[ÒÓÔÕÖØ]/g,
			'r': /[řŕ]/g,
			'R': /[ŘŔ]/g,
			's': /[ššş]/g,
			'S': /[ŠŞŚ]/g,
			't': /[ťţ]/g,
			'T': /[ŤŢ]/g,
			'ue': /[ü]/g,
			'UE': /[Ü]/g,
			'u': /[ùúûůµ]/g,
			'U': /[ÙÚÛŮ]/g,
			'y': /[ÿý]/g,
			'Y': /[ŸÝ]/g,
			'z': /[žźż]/g,
			'Z': /[ŽŹŻ]/g,
			'th': /[þ]/g,
			'TH': /[Þ]/g,
			'dh': /[ð]/g,
			'DH': /[Ð]/g,
			'ss': /[ß]/g,
			'oe': /[œ]/g,
			'OE': /[Œ]/g,
			'ae': /[æ]/g,
			'AE': /[Æ]/g
		},

		tidy = {
			' ': /[\xa0\u2002\u2003\u2009]/g,
			'*': /[\xb7]/g,
			'\'': /[\u2018\u2019]/g,
			'"': /[\u201c\u201d]/g,
			'...': /[\u2026]/g,
			'-': /[\u2013]/g,
			//	'--': /[\u2014]/g,
			'&raquo;': /[\uFFFD]/g
		};

		var walk = function (string, replacements) {
			var result = string, key;
			for (key in replacements) result = result.replace(replacements[key], key);
			return result;
		};

		var getRegexForTag = function (tag, contents) {
			tag = tag || '';
			var regstr = contents ? "<" + tag + "(?!\\w)[^>]*>([\\s\\S]*?)<\/" + tag + "(?!\\w)>" : "<\/?" + tag + "([^>]+)?>",
					reg = new RegExp(regstr, "gi");
			return reg;
		};

		String.implement({

			// Removes non-ascii characters and converts them to their most appropriate ascii character
			// 
			// Syntax: myString.standardize();
			// 
			// Arguments: N/A
			// 
			// Returns: 
			//	(string) a string without any non-ascii characters.
			// 
			// Examples: 
			//	var bjorkProper = "BjÃƒÂ¶rk";
			//	var bjorkAscii = bjorkProper.standardize(); //returns "Bjork"
			standardize: function () {
				return walk(this, special);
			},

			// Repeats a string a specified number of times
			// 
			// Syntax: myString.repeat(times);
			// 
			// Arguments: 
			//	times - (number) The number of times to repeat the string.
			// 
			// Returns: 
			//	(string) the string repeated the specified number of times
			// 
			// Examples: 
			//	var one = "1";
			//	var eleventyOne = one.repeat(3); //returns "111"
			repeat: function (times) {
				return new Array(times + 1).join(this);
			},

			// Pads a string with the specified character(s) either before or after the current value
			// 
			// Syntax: myString.pad(length, string, direction);
			// 
			// Arguments: 
			//	length - (number) the number of characters to pad.
			//	string - (string) the string to use for padding; defaults to a space.
			//	direction - (string) either "left", "right" or "both" (defaults to "right"); the side to add the padding.
			// 
			// Returns: 
			//	(string) a string with the specified character repeated the specified number of times either to the right or left of the current value.
			// 
			// Examples: 
			//	var tonyTheTigerSez = "They're gr".pad(15, 'r') + 'eat!'; //returns "They're grrrrrreat!"
			pad: function (length, str, direction) {
				if (this.length >= length) { return this; }

				var pad = (str == null ? ' ' : '' + str)
						.repeat(length - this.length)
						.substr(0, length - this.length);

				if (!direction || direction == 'right') {
					return this + pad;
				}
				if (direction == 'left') {
					return pad + this;
				}

				return pad.substr(0, (pad.length / 2).floor()) + this + pad.substr(0, (pad.length / 2).ceil());
			},

			// Get all the HTML tags from a given string
			// 
			// Syntax: myString.getTags([tag, contents]);
			// 
			// Arguments: 
			//	tag - (string; optional) if defined, returns the tags of the specified type in an array. If not defined, returns all tags in an array.
			//	contents - (boolean; optional) if true, you are returned an array of tag matches and their contents.
			// 
			// Returns: 
			//	(array) An array of strings for each matched tag (important note: NOT elements, strings)
			// 
			// Examples: 
			//	var html = "<b>This is a string with <i>html</i> in it.</b>"
			//	var tags = html.getTags(); //returns ["<b>", "<i>", "</i>", "</b>"]
			//	var italics = html.getTags('i'); //returns ["<i>", "</i>"]
			//	var italicsWithContent = html.getTags('i', true); //returns ["<i>html</i>"]
			getTags: function (tag, contents) {
				return this.match(getRegexForTag(tag, contents)) || [];
			},

			// Remove all html tags from a string
			// 
			// Syntax: myString.stripTags([tag, contents]);
			// 
			// Arguments: 
			//	tag - (string; optional) if defined, returns the tags of the specified type in an array. If not defined, returns all tags in an array.
			//	contents - (boolean; optional) if true, you are returned an array of tag matches and their contents.
			// 
			// Returns: 
			//	(string) a string with the appropriate HTML stripped
			// 
			// Examples: 
			//	var html = "<b>This is a string with <i>html</i> in it.</b>"
			//	var noHtml = html.stripTags(); //returns "This is a string with html in it."
			//	var noItalics = html.stripTags('i'); //returns "<b>This is a string with html in it.</b>"
			//	var noItalicsContent = html.stripTags('i', true); //returns "<b>This is a string with  in it.</b>"
			stripTags: function (tag, contents) {
				return this.replace(getRegexForTag(tag, contents), '');
			},

			// Replaces common special characters with their ASCII counterparts (smart quotes, elipse characters, stuff from MS Word, etc.).
			// 
			// Syntax: var tidyString = stringWithBadChars.tidy();
			// 
			// Arguments: N/A
			// 
			// Returns: 
			//	(string) the string with the non-ASCII characters replaced
			// 
			// Examples: 
			// 
			tidy: function () {
				return walk(this, tidy);
			},

			// Truncates a string after the given number of characters
			// 
			// Syntax: myString.truncate(max, trail, atChar);
			// 
			// Arguments: 
			//	max - (number) the maximum length of the string.
			//	trail - (string, optional) the trail which will be appended to the string when it is truncated, defaults to â€¦ when only the max argument is passed.
			//	atChar - (string, optional) a string which be truncated after. For example before a space.
			// 
			// Returns: 
			//	(string) the truncated string
			// 
			// Examples: 
			//	'This is some random text'.truncate(15); // This is some raÃ¢Â€Â¦
			//	'This is some random text'.truncate(15, '--'); // This is some ra--
			//	'This is some random text'.truncate(15, 'Ã¢Â€Â¦', ' '); // This is someÃ¢Â€Â¦
			truncate: function (max, trail, atChar) {
				var string = this;
				if (trail == null && arguments.length == 1) {
					trail = '…';
				}
				if (string.length > max) {
					string = string.substring(0, max);
					if (atChar) {
						var index = string.lastIndexOf(atChar);
						if (index != -1) {
							string = string.substr(0, index);
						}
					}
					if (trail) { string += trail; }
				}
				return string;
			}

		});

	})();

	// #endregion

	// #region - String.QueryString -

	/*
	---

	script: String.QueryString.js

	name: String.QueryString

	description: Methods for dealing with URI query strings.

	license: MIT-style license

	authors:
	- Sebastian Markbåge
	- Aaron Newton
	- Lennart Pilon
	- Valerio Proietti

	requires:
	- Core/Array
	- Core/String
	- /MooTools.More

	provides: [String.QueryString]

	...
	*/

	String.implement({

		// Turns a querystring into an object of key/value pairs
		// 
		// Syntax: myString.parseQueryString(decodeKeys, decodeValues);
		// 
		// Arguments: 
		//	decodeKeys - (boolean, optional) if set to false, keys are passed through [decodeURIComponent][]; defaults to true
		//	decodeValues - (boolean, optional) if set to false, values are passed through [decodeURIComponent][]; defaults to true
		// 
		// Returns: 
		//	(object) the querystring as key/value pairs
		// 
		// Examples: 
		//	"apple=red&lemon=yellow".parseQueryString(); //returns { apple: "red", lemon: "yellow }
		//	var fruits = "apple=red&lemon=yellow".parseQueryString();	//returns fruits.apple > "red"
		parseQueryString: function (decodeKeys, decodeValues) {
			if (decodeKeys == null) { decodeKeys = true; }
			if (decodeValues == null) { decodeValues = true; }

			var vars = this.split(/[&;]/),
					object = {};
			if (!vars.length) { return object; }

			vars.each(function (val) {
				var index = val.indexOf('=') + 1,
				value = index ? val.substr(index) : '',
				keys = index ? val.substr(0, index - 1).match(/([^\]\[]+|(\B)(?=\]))/g) : [val],
				obj = object;
				if (!keys) { return; }
				if (decodeValues) { value = decodeURIComponent(value); }
				keys.each(function (key, i) {
					if (decodeKeys) { key = decodeURIComponent(key); }
					var current = obj[key];

					if (i < keys.length - 1) {
						obj = obj[key] = current || {};
					} else if (typeOf(current) == 'array') {
						current.push(value);
					} else {
						obj[key] = current != null ? [current, value] : value;
					}
				});
			});

			return object;
		},

		// Removes from a query string any keys that have empty values.
		// 
		// Syntax: myQueryString.cleanQueryString([method]);
		// 
		// Arguments: 
		//	method - (funciton, optional) a method passed to [Array.filter][] that returns true if a key/value set should be included. 
		//																Defaults to a method that checks that the value is not an empty string.
		// 
		// Returns: 
		//	(string) the string appropriate key/values removed
		// 
		// Examples: 
		//	var cleaned = "a=b&x=&z=123&e=".cleanQueryString();	//cleaned = "a=b&z=123"
		//	var noNumberValues = "a=b&x=y&z=123&e=".cleanQueryString(function(set){
		//		//set is "a=b", "x=y", "z=123", "e="
		//		return !set.split("=")[1].match(/[0-9]/);
		//	});  //noNumberValues = "a=b&x=y&e="
		cleanQueryString: function (method) {
			return this.split('&').filter(function (val) {
				var index = val.indexOf('='),
				key = index < 0 ? '' : val.substr(0, index),
				value = val.substr(index + 1);

				return method ? method.call(null, key, value) : (value || value === 0);
			}).join('&');
		}

	});

	// #endregion

	// #endregion

	// #region -- Browser --

	/*
	---

	name: Browser

	description: The Browser Object. Contains Browser initialization, Window and Document, and the Browser Hash.

	license: MIT-style license.

	requires: [Array, Function, Number, String]

	provides: [Browser, Window, Document]

	...
	*/

	(function () {

		var document = this.document;
		var window = document.window = this;

		var UID = 1;

		// 检测是否为<ltIE7>
		this.$uid = (window.ActiveXObject) ? function (item) {
			return (item.uid || (item.uid = [UID++]))[0];
		} : function (item) {
			return item.uid || (item.uid = UID++);
		};

		// 仅仅为客户端对象window以及document设置uid
		$uid(window);
		$uid(document);

		// #region - Browser -

		// Some browser properties are attached to the Browser Object for browser and platform detection
		// 渲染引擎的检测是完全建立在浏览器的功能特性上的

		// 浏览器检测相关
		var ua = navigator.userAgent.toLowerCase(),
				platform = navigator.platform.toLowerCase(),
				UA = ua.match(/(opera|ie|firefox|chrome|version)[\s\/:]([\w\d\.]+)?.*?(safari|version[\s\/:]([\w\d\.]+)|$)/) || [null, 'unknown', 0],
				mode = UA[1] == 'ie' && document.documentMode;

		var Browser = this.Browser = {

			// 使得Browser对象也有继承的能力
			extend: Function.prototype.extend,

			// 返回当前浏览器的名称
			name: (UA[1] == 'version') ? UA[3] : UA[1],

			// 返回当前浏览器的版本
			version: mode || parseFloat((UA[1] == 'opera' && UA[4]) ? UA[4] : UA[2]),

			// 返回当前操作系统名称
			Platform: {
				name: ua.match(/ip(?:ad|od|hone)/) ? 'ios' : (ua.match(/(?:webos|android)/) || platform.match(/mac|win|linux/) || ['other'])[0]
			},

			// Browser.Features.xpath - (boolean) True if the browser supports DOM queries using XPath.(当前浏览器是否支持XPath进行DOM查询)
			// Browser.Features.air - (boolean) True if the browser supports AIR.
			// Browser.Features.query - (boolean) True if the browser supports querySelectorAll.
			// Browser.Features.json - (boolean) True if the browser has a native JSON object.
			Features: {
				xpath: !!(document.evaluate),
				air: !!(window.runtime),
				query: !!(document.querySelector),
				json: !!(window.JSON)
			},

			Plugins: {}

		};

		// 浏览器渲染引擎相关
		// Browser.ie - (boolean) True if the current browser is Internet Explorer.
		// Browser.ie6 - (boolean) True if the current browser is Internet Explorer 6.
		// Browser.ie7 - (boolean) True if the current browser is Internet Explorer 7.
		// Browser.ie8 - (boolean) True if the current browser is Internet Explorer 8.
		// Browser.firefox - (boolean) True if the current browser is Firefox
		// Browser.firefox2 - (boolean) True if the current browser is Firefox 2
		// Browser.firefox3 - (boolean) True if the current browser is Firefox 3
		// Browser.safari - (boolean) True if the current browser is Safari
		// Browser.safari3 - (boolean) True if the current browser is Safari 3
		// Browser.safari4 - (boolean) True if the current browser is Safari 4
		// Browser.chrome - (boolean) True if the current browser is Chrome
		// Browser.opera - (boolean) True if the current browser is Opera
		// If an IE document is set to backwards compatibility mode using the X-UA-Compatible header, then the Browser object is treated as if the earlier version of the browser is running
		Browser[Browser.name] = true;
		Browser[Browser.name + parseInt(Browser.version, 10)] = true;
		// 操作系统平台
		// Browser.Platform.mac - (boolean) True if the platform is Mac.
		// Browser.Platform.win - (boolean) True if the platform is Windows.
		// Browser.Platform.linux - (boolean) True if the platform is Linux.
		// Browser.Platform.ios - (boolean) True if the platform is iOS.
		// Browser.Platform.android - (boolean) True if the platform is Android
		// Browser.Platform.webos - (boolean) True if the platform is WebOS
		// Browser.Platform.other - (boolean) True if the platform is neither Mac, Windows, Linux, Android, WebOS nor iOS.
		// Browser.Platform.name - (string) The name of the platform.
		Browser.Platform[Browser.Platform.name] = true;

		// Browser.Request - (object) The XMLHTTP object or equivalent.
		// 第一次使用Browser.Request()，会进行attempt
		// 第一次之后调用则相当于
		//
		//	Browser.Request=function(){
		//		return new XMLHttpRequest();
		//	} //假设在W3C浏览器下
		// 函数的后置绑定
		Browser.Request = (function () {

			var XMLHTTP = function () {
				return new XMLHttpRequest();
			};

			var MSXML2 = function () {
				return new ActiveXObject('MSXML2.XMLHTTP');
			};

			var MSXML = function () {
				return new ActiveXObject('Microsoft.XMLHTTP');
			};

			return Function.attempt(function () {
				XMLHTTP();
				return XMLHTTP;
			}, function () {
				MSXML2();
				return MSXML2;
			}, function () {
				MSXML();
				return MSXML;
			});

		})();

		// 是否支持xmlHttpRequest或ActiveXObject
		// Browser.Features.xhr - (boolean) True if the browser supports native XMLHTTP object.(当前浏览器是否支持原生的XMLHTTP对象)
		Browser.Features.xhr = !!(Browser.Request);

		// Flash detection(能力检测)
		// Browser.Plugins.Flash - (boolean) - True if Flash is present.

		var version = (Function.attempt(function () {
			return navigator.plugins['Shockwave Flash'].description;
		}, function () {
			return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version');
		}) || '0 r0').match(/\d+/g);

		// Browser.Plugins.Flash.version - (number) 当前浏览器安装的flash插件的主版本号
		// Browser.Plugins.Flash.build - (number) 当前浏览器安装的flash插件的子版本号
		Browser.Plugins.Flash = {
			version: Number(version[0] || '0.' + version[1]) || 0,
			build: Number(version[2]) || 0
		};

		// String scripts
		// 动态执行传入的javascript代码片段并执
		Browser.exec = function (text) {
			if (!text) { return text; }
			if (window.execScript) {
				window.execScript(text);
			} else {
				var script = document.createElement('script');
				script.setAttribute('type', 'text/javascript');
				script.text = text;
				document.head.appendChild(script);
				document.head.removeChild(script);
			}
			return text;
		};

		// #endregion Browser

		// #region - String.stripScripts -

		// 剥离字符串中 标签包围的部分
		// 
		// Syntax: 
		//	myString.stripScripts([evaluate]);
		// 
		// Arguments: 
		//	evaluate - (boolean, 可选) 如果设置了 evaluate 为 true, 字符串中的脚本将会被执行
		// 
		// Returns: 
		//	(string) - 剥离了脚本的字符串
		// 
		// Examples: 
		// 去除str中的script标签以及之中的代码
		String.implement('stripScripts', function (exec) {
			var scripts = '';
			// 如果传入的RegExp对象有g全局参数，则替换所有满足的子字符串
			var text = this.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, function (all, code) {
				scripts += code + '\n';
				return '';
			});
			if (exec === true) {
				Browser.exec(scripts);
			} else if (typeOf(exec) == 'function') {
				exec(scripts, text);
			}
			// 返回去除javascript代码的文本
			return text;
		});

		// #endregion String.stripScripts

		// #region - Window, Document -

		/**
		* 开始用Type包装Document 与Window了
		* 除了IE 大部分浏览器暴露了element的构造函数 Element可以通过赋值给
		* Element.prototype来使 节点对象获得方法
		**/
		Browser.extend({
			Document: this.Document,
			Window: this.Window,
			Element: this.Element,
			Event: this.Event
		});

		// 区别window 与 document  首字母大写了 Window相当于window的构造函数  
		// 这样 instanceOf(window) 返回值就为Window了 仅仅只是一种伪造
		this.Window = this.$constructor = new Type('Window', function () { });

		// 将window的typeOf返回值设为window
		this.$family = Function.from('window').hide();

		// 到目前为止 Type.prototype.mirror的第一次使用
		// 把这个闭包函数推入 hooks.window的即Window类型的Type实例
		// 对应的钩子函数数组，由于Window并不是window真正的构造函数
		// （仅仅只是指定了window的typeOf与instanceOf的值,注意区别typeof与instanceof）
		// 这个推入的闭包函数的作用就是当Window.implement时,虽然不能通过
		// 扩展Window.prototype来使 window获得对应的方法,但可以手动添加window的对象方法
		// 算是一种虚构 的 原型的扩展吧  挺帅的。
		Window.mirror(function (name, method) {
			window[name] = method;
		});

		// 与window类似的处理document 的$constructor 与$family 还有mirror
		// 这样所有Document   implement的方法 都能被document一并继承
		this.Document = document.$constructor = new Type('Document', function () { });

		document.$family = Function.from('document').hide();

		Document.mirror(function (name, method) {
			document[name] = method;
		});

		// 简写
		document.html = document.documentElement;
		if (!document.head) {
			document.head = document.getElementsByTagName('head')[0];
		}

		if (document.execCommand) {
			try {
				// 解决IE6下图片作为背景时，不缓存这个图片的bug,在现今CSS Sprite横行的年代
				// 背景图片不缓存这个将带来严重抖动，因为每次都会发起一个请求,会有时延
				document.execCommand("BackgroundImageCache", false, true);
			} catch (e) { }
		}

		// #region ltIE9

		if (this.attachEvent && !this.addEventListener) {
			// IE9以下的IE浏览器 在关闭 onunload不会触发  利用attachEvent可以解决这个问题
			var unloadEvent = function () {
				this.detachEvent('onunload', unloadEvent);
				document.head = document.html = document.window = null;
			};
			this.attachEvent('onunload', unloadEvent);
		}

		// IE fails on collections and <select>.options (refers to <select>)
		// fixed IE下 Array.from报错 比如item参数为NodeList 等类数组集合
		var arrayFrom = Array.from;
		try {
			arrayFrom(document.html.childNodes);
		} catch (e) {
			// 捕捉到异常则为IE浏览器，重新定义from不以slice的方式，而采用遍历推入新数组的方式
			Array.from = function (item) {
				if (typeof item != 'string' && Type.isEnumerable(item) && typeOf(item) != 'array') {
					var i = item.length,
							array = new Array(i);
					while (i--) {
						array[i] = item[i];
					}
					return array;
				}
				return arrayFrom(item);
			};

			// 利用修正了的Array.from来实现Array的实例方法的静态化
			var prototype = Array.prototype,
					slice = prototype.slice;
			['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice'].each(function (name) {
				var method = prototype[name];
				Array[name] = function (item) {
					return method.apply(Array.from(item), slice.call(arguments, 1));
				};
			});
		}

		// #endregion ltIE9

		// #endregion Window, Document

	})();

	// #endregion

	// #region -- Event --

	/*
	---

	name: Event

	description: Contains the Event Type, to make the event object cross-browser.

	license: MIT-style license.

	requires: [Window, Document, Array, Function, String, Object]

	provides: Event

	...
	*/

	(function () {

		var _keys = {};

		// Event Methods.
		// 
		// Syntax: new Event([event[, win]]);
		// 
		// Arguments: 
		//	event - (event, required) An HTMLEvent Object.
		//	win - (window, optional: defaults to window) The context of the event.
		// 
		// Properties:
		//	page.x - (number) The x position of the mouse, relative to the full window.(鼠标相对整个window的x坐标)
		//	page.y - (number) The y position of the mouse, relative to the full window.(鼠标相对整个window的y坐标)
		//	client.x - (number) The x position of the mouse, relative to the viewport.(鼠标相对整个页面可视区域的x坐标)
		//	client.y - (number) The y position of the mouse, relative to the viewport.(鼠标相对整个页面可视区域的y坐标)
		//	rightClick - (boolean) True if the user clicked the right mousebutton(用户是否按下鼠标右键)
		//	wheel - (number) The amount of third button scrolling.(鼠标滚轮的滚动量)
		//	relatedTarget - (element) The event related target.(事件目标的参照对象)
		//	target - (element) The event target.(事件目标对象)
		//	code - (number) The keycode of the key pressed.(按键的键盘代码)
		//	key - (string) The key pressed as a lowercase string. key can be 'enter', 'up', 'down', 'left', 'right', 'space', 'backspace', 'delete', and 'esc'.
		//									按键的名称. 可为如下: 'enter', 'up', 'down', 'left', 'right', 'space', 'backspace', 'delete', 以及 'esc'
		//	shift - (boolean) True if the user pressed the shift key.(用户是否按下shift键)
		//	control - (boolean) True if the user pressed the control key.(用户是否按下control键)
		//	alt - (boolean) True if the user pressed the alt key.(用户是否按下alt键)
		//	meta - (boolean) True if the user pressed the meta key.(用户是否按下meta键)
		//
		// Notes: 
		//	Accessing event.page / event.client requires the page to be in Standards Mode.(要正确获取event.page / event.client, 则需要页面使用标准模式的DOCTYPE)
		//	Every event added with addEvent gets the MooTools method automatically, without the need to manually instance it.(每个使用addEvent方法添加的事件event对象将自动获取到mootools提供的方法扩展, 不需要再去手工创建实例)
		// 
		// Examples: 
		//	$('myLink').addEvent('keydown', function(event){
		//		// the passed event parameter is already an instance of the Event class.(传入的event已经是一个Event类的示例)
		//		alert(event.key);   // returns the lowercase letter pressed.
		//		alert(event.shift); // returns true if the key pressed is shift.
		//		if (event.key == 's' && event.control) alert('Document saved.'); //executes if the user presses Ctr+S.(Ctr + S 组合键)
		//	});
		var DOMEvent = this.DOMEvent = new Type('DOMEvent', function (event, win) {
			if (!win) { win = window; }
			// 在IE下，event对象是一个window全局属性
			event = event || win.event;
			// 如果这个事件对象已经是被包装过的，则返回这个event不作处理
			if (event.$extended) { return event; }
			this.event = event;
			// 表明event是否被封装过的标志
			this.$extended = true;
			this.shift = event.shiftKey;
			this.control = event.ctrlKey;
			this.alt = event.altKey;
			this.meta = event.metaKey;
			// 比如mouseover等等
			var type = this.type = event.type;
			// 取得事件直接关联的dom对象的引用
			var target = event.target || event.srcElement;
			// 在Safari下 target有可能指向的是文本节点 修正这个错误
			while (target && target.nodeType == 3) {
				target = target.parentNode;
			}
			this.target = document.id(target);

			// 如果是键盘事件，统一各浏览器下的keyCode
			if (type.indexOf('key') == 0) {
				var code = this.code = (event.which || event.keyCode);
				// 根据keyCode来获取按下特殊键的名称 如left等 在下面会有定义Keys字面量对象
				this.key = _keys[code];
				if (type == 'keydown') {
					if (code > 111 && code < 124) {
						this.key = 'f' + (code - 111);
					} else if (code > 95 && code < 106) {
						this.key = code - 96;
					}
				}
				if (this.key == null) {
					this.key = String.fromCharCode(code).toLowerCase();
				}
			} else if (type == 'click' || type == 'dblclick' || type == 'contextmenu' || type == 'DOMMouseScroll' || type.indexOf('mouse') == 0) {
				// 确定doc文档模式,主要是由于IE在compatMode='CSS1Compat' (标准模式)与'BackCompat'(怪异模式)下的
				// 盒模型的渲染有区别。怪异模式下 页面的滚动值 clientWidth、clientHeight、scrollWidth、scrollHeight等都是
				// 通过document.body获取的。而在标准模式下 则使用document.HTMLElement获取 (也就是下面的doc.body与doc.html)
				var doc = win.document;
				doc = (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body;
				this.page = {
					// pageX:FF特有，鼠标在页面上的位置，IE没有直接替换的属性.
					// 其实并不是所有都是IE在作怪 FF也有逆天而行的layerX属性和DOMMouseScroll等等
					x: (event.pageX != null) ? event.pageX : event.clientX + doc.scrollLeft,
					y: (event.pageY != null) ? event.pageY : event.clientY + doc.scrollTop
				};
				this.client = {
					// window.pageXOffset返回浏览器视口左上角相对整个页面的x
					x: (event.pageX != null) ? event.pageX - win.pageXOffset : event.clientX,
					y: (event.pageY != null) ? event.pageY - win.pageYOffset : event.clientY
				};
				// 如果是滚动事件,(FF下世DOMMouseScroll)
				if (type == 'DOMMouseScroll' || type == 'mousewheel') {
					// mousewheel中向上滚动为正 返回值最小单位为120,
					// FF下DOMMouseScroll向下为正!!!,返回值是的最小单位为3,所以一并除以120或者3,统一滚动量
					// Opera两面倒都支持....
					this.wheel = (event.wheelDelta) ? event.wheelDelta / 120 : -(event.detail || 0) / 3;
				}

				// IE下 1左键  2中键  3右键       W3C 则1是左键  2是右键
				this.rightClick = (event.which == 3 || event.button == 2);
				// mouseover与mouseout事件有相关的related目标,
				// 即代表over前的dom对象 以及 out前的dom对象....
				if (type == 'mouseover' || type == 'mouseout') {
					var related = event.relatedTarget || event[(type == 'mouseover' ? 'from' : 'to') + 'Element'];
					while (related && related.nodeType == 3) {
						related = related.parentNode;
					}
					this.relatedTarget = document.id(related);
				}
				// 移动设备的page与client
			} else if (type.indexOf('touch') == 0 || type.indexOf('gesture') == 0) {
				this.rotation = event.rotation;
				this.scale = event.scale;
				this.targetTouches = event.targetTouches;
				this.changedTouches = event.changedTouches;
				var touches = this.touches = event.touches;
				if (touches && touches[0]) {
					var touch = touches[0];
					this.page = { x: touch.pageX, y: touch.pageY };
					this.client = { x: touch.clientX, y: touch.clientY };
				}
			}

			if (!this.client) { this.client = {}; }
			if (!this.page) { this.page = {}; }
		});

		DOMEvent.implement({

			// Stop an Event from propagating and also executes preventDefault(停止事件传播和中止执行事件的默认行为)
			// 
			// Syntax: myEvent.stop();
			// 
			// Arguments: N/A
			// 
			// Returns: 
			//	(object) This Event instance.
			// 
			// Examples: 
			//	HTML Code: <a id="myAnchor" href="http://google.com/">Visit Google.com</a>
			//	JS Code:
			//	$('myAnchor').addEvent('click', function(event){
			//		event.stop(); //Prevents the browser from following the link.(阻止链接的默认行为: 打开链接到google.com)
			//		this.set('text', 'Where do you think you\'re going?'); //'this' is Element that fires the Event.
			//		(function(){
			//			this.set('text','Instead visit the Blog.').set('href', 'http://blog.mootools.net');
			//		}).delay(500, this);
			//	});
			//
			// Notes:
			//	Returning false within the function can also stop the propagation of the Event.(在事件监听函数中返回false的话, 同样也可起到停止事件传播的效果)
			stop: function () {
				return this.preventDefault().stopPropagation();
			},

			// Cross browser method to stop the propagation of an event (this stops the event from bubbling up through the DOM).
			// 停止事件的传播(停止事件在DOM结构中进行冒泡传递)
			// 
			// Syntax: myEvent.stopPropagation();
			// 
			// Arguments: N/A
			// 
			// Returns: (object) This Event object.
			// 
			// Examples: 
			// 
			stopPropagation: function () {
				if (this.event.stopPropagation) {
					this.event.stopPropagation();
				} else {
					this.event.cancelBubble = true;
				}
				return this;
			},

			// Cross browser method to prevent the default action of the event.
			// 中止执行事件的默认行为
			// 
			// Syntax: myEvent.preventDefault();
			// 
			// Arguments: N/A
			// 
			// Returns: (object) This Event object
			// 
			// Examples: 
			// 
			preventDefault: function () {
				if (this.event.preventDefault) {
					this.event.preventDefault();
				} else {
					this.event.returnValue = false;
				}
				return this;
			}

		});

		DOMEvent.defineKey = function (code, key) {
			_keys[code] = key;
			return this;
		};

		DOMEvent.defineKeys = DOMEvent.defineKey.overloadSetter(true);

		DOMEvent.defineKeys({
			'38': 'up',
			'40': 'down',
			'37': 'left',
			'39': 'right',

			'27': 'esc',
			'32': 'space',
			'8': 'backspace',
			'9': 'tab',

			'46': 'delete',
			'13': 'enter'
		});

	})();

	// #endregion

	// #region -- Class --

	// #region - Class -

	/*
	---

	name: Class

	description: Contains the Class Function for easily creating, extending, and implementing reusable Classes.

	license: MIT-style license.

	requires: [Array, String, Function, Number]

	provides: Class

	源码分析: 苦苦的苦瓜(http://hmking.blog.51cto.com)

	...
	*/

	(function () {

		// #region Class

		var Class = this.Class = new Type('Class', function (params) {
			// 如果参数是一个函数，当作构造函数处理，自动变为一个对象字面量，例如：
			// var Barn = new Class(function(name){ this.fowl = name; });
			if (instanceOf(params, Function)) {
				params = { initialize: params };
			}

			// 先新建一个函数作为新建的类的原型
			// 然后调用extend函数把Class所有的特性复制给newClass
			// 然后params对象implement到newClass类中，这里调用的implement是Class的implement方法
			var newClass = function () {
				// 复制前先解除关联，为什么要剥离?因为原型继承，包含引用类型的原型属性会被所有实例共享啊......
				reset(this);
				// 判断是否处于类的设计阶段
				if (newClass.$prototyping) { return this; }
				this.$caller = null;
				// 类的实例运行阶段调用类本身的构造函数，将参数原样传递
				var value = (this.initialize) ? this.initialize.apply(this, arguments) : this;
				this.$caller = this.caller = null;
				return value;
			} .extend(this).implement(params);

			// 将newClass的构造函数设为Class
			newClass.$constructor = Class;
			// 指定newClass的原型的$constructor，使之可以正确的instanceOf
			newClass.prototype.$constructor = newClass;
			// this.parent可以访问父类的被覆盖的方法
			newClass.prototype.parent = parent;

			// 返回了这个被包装过的类
			return newClass;
		});

		// this.parent可以访问父类的被覆盖的方法
		var parent = function () {
			if (!this.$caller) {
				throw new Error('The method "parent" cannot be called.');
			}
			// 通过$name属性取得类方法名称
			var name = this.$caller.$name,
			// 通过$owner属性得到类对象(不是类的实例)，调用类的静态属性parent的到父类对象
					parent = this.$caller.$owner.parent,
			// 取得父类原型中的同名方法
					previous = (parent) ? parent.prototype[name] : null;
			// 如果父类中不存在同名的方法，它就抛出一个错误
			if (!previous) {
				throw new Error('The method "' + name + '" has no parent.');
			}
			// 调用父类中的方法
			return previous.apply(this, arguments);
		};

		/**
		* 对象的剥离(也就是clone),这里要详细说明一下reset函数的工作原理：
		* 首先创建了一个新的空函数F，然后将F的prototype属性设置为作为参数object传入的原型对象，prototype属性就是用来指向原型对象的，通过原型链机制，
		* 它提供了到所有继承而来的成员的链接，最后通过new运算符作用于F创建出一个新对象返回。这个新的对象就是一个以给定对象为原型对象的空对象，
		* 以下面的例子来解说，先执行reset(b)语句，然后读取b.ref.x的值，这时你得到的是其原型对象的同名属性值，其实是一个返指最初的a.x的链接，
		* 而在这之后你写入b.ref.x一个新值，也就是直接为b.ref对象定义了一个新的属性x，这时你再读取b.ref.x就不是指向a.x了
		* 如果想详细了解原型式继承可翻阅JavaScript设计模式一书，非常棒的一本书，真的很棒!!!哈哈......
		* var a = { x: 1 };
		* var b = { y: 2, ref: a };
		* log.info('b.ref == a : ' + (b.ref == a)); //输出true
		* log.info(b.y); // 输出2
		* log.info(b.ref.x); // 输出1
		* reset(b); //解除引用
		* log.info('b.ref == a : ' + (b.ref == a)); //输出false
		* log.info(b.y); // 输出2
		* log.info(b.ref.x); // 输出1
		* b.ref.x = 10;
		* log.info(b.ref.x); // 输出10
		* log.info(a.x); // 输出1
		**/
		var reset = function (object) {
			for (var key in object) {
				var value = object[key];
				switch (typeOf(value)) {
					case 'object':
						var F = function () { };
						F.prototype = value;
						object[key] = reset(new F);
						break;

					case 'array':
						object[key] = value.clone();
						break;
				}
			}
			return object;
		};

		/**
		* @function: wrap
		* @description: 将一个方法用wrapper函数重新包装，添加下面几个静态属性
		* @$owner - 类本身
		* @$origin - 指向未被包装的函数
		* @$name - 类的方法名称
		* @returns: (funciton) 包装过后的函数
		**/
		var wrap = function (self, key, method) {
			// 如果函数已被父类包装过，则调用最初未被包装的函数(函数的原始形态，呵呵)
			if (method.$origin) {
				method = method.$origin;
			}
			var wrapper = function () {
				// 如果方法设置了$protected属性，说明此方法不希望在类外面被调用，也就是类的实例不能调用类中设置了$protected属性的方法，只可远观而不可亵玩也，呵呵......
				// 但是如果一个类继承另一个类，同时在子类中覆盖了父类中设置了$protected属性的方法，在子类的实例中调用此方法就不会弹出错误警告了。
				// 当然如果子类的同名方法同样设置了$protected属性，那么子类的实例同样不能调用此方法。
				if (method.$protected && this.$caller == null) {
					throw new Error('The method "' + key + '" cannot be called.');
				}
				// 缓存类实例的caller和$caller两个属性
				var caller = this.caller,
						current = this.$caller;
				this.caller = current;
				// 将类实例的$caller属性指向调用的方法本身，Function的caller属性在Class中的完美模拟，这样parent函数才可以运行啊，呵呵......
				this.$caller = wrapper;
				// 挂为原型上的方法执行
				var result = method.apply(this, arguments);
				// 方法执行完毕将类实例caller和$caller两个属性值还原
				this.$caller = current;
				this.caller = caller;
				return result;
			} .extend({ $owner: self, $origin: method, $name: key });
			return wrapper;
		};

		// 又见implement函数，第三次了，呵呵，这里是扩展类的方法属性
		var implement = function (key, value, retain) {
			// 首先检查类的的每一个属性和方法在Class.Mutators对象的是不是有mutator函数的对应的名字在里面。
			// 如果找到了，它就调用这个函数并且把键的值传给它做处理。
			if (Class.Mutators.hasOwnProperty(key)) {
				value = Class.Mutators[key].call(this, value);
				// 判断mutator函数有没有返回值，如果没有则退出。
				if (value == null) { return this; }
			}

			if (typeOf(value) == 'function') {
				// $hidden属性表明此函数无法被其他对象implement
				if (value.$hidden) { return this; }
				// Implements mutator调用本函数时retain参数设为ture，表明只是合并方法到原型中
				// 而在创建类时(前面建立newclass)retain参数没有赋值，执行wrap函数包装方法到原型
				this.prototype[key] = (retain) ? value : wrap(this, key, value);
			} else {
				// 合并属性到原型
				Object.merge(this.prototype, key, value);
			}

			return this;
		};

		/**
		* @functoin: getInstance
		* @param klass - (class) 要继承的类
		* @description: 得到父类的一个实例
		**/
		var getInstance = function (klass) {
			// 设置标记，说明Class在设计阶段，不会执行构造函数
			klass.$prototyping = true;
			var proto = new klass;
			// 删除标记
			delete klass.$prototyping;
			return proto;
		};

		// 暴露implement方法
		Class.implement('implement', implement.overloadSetter());

		// #endregion Class

		// #region Mutators

		/**
		* 好了，接下来着重介绍一下Class.Mutators对象：
		*
		* Mutator是一个可以改变你的类的结构的一个很特殊的函数，它们是产生特别功能和优雅化继承和掺元的的有力工具。
		*
		* 建立一个Mutatorr有二个部分：mutator的关键字 和mutator的实际函数，关键字既是mutator的名字，
		* 也是在构建类时候的keyword。Mootools把mutators 储存在Class.Mutators对象中。
		*
		* 当你传一个对象给Class构造函数的时候，Mootools检查这个对象的的每一个键在Class.Mutators对象的是不是有
		* mutator函数的对应的名字在里面。如果找到了，它就调用这个函数并且把键的值传给它做处理。
		*
		* Class.Mutators对象包含了两个内建的Mutator: Extends 和 Implements，分别实现原型式继承和多亲继承。
		*
		* MooTools在Class.Extras模块中提供了三个掺元类Chain、Events、Options，至于作用就不用多说了吧，呵呵。
		**/
		Class.Mutators = {

			// 取得传送给它的class的名字后，直接继承这个class
			Extends: function (parent) {
				// 静态属性，存储父类对象
				this.parent = parent;
				// 原型式继承
				this.prototype = getInstance(parent);
			},

			// Implements mutator取得传送给它的class的名字后，把它们的方法和属性添加到新类。
			// 利用掺元类实现多亲继承
			Implements: function (items) {
				Array.from(items).each(function (item) {
					var instance = new item;
					for (var key in instance) {
						implement.call(this, key, instance[key], true);
					}
				}, this);
			}
		};

		// #endregion

	})();

	// #endregion

	// #region - Class.Extras -

	/*
	---

	name: Class.Extras

	description: Contains Utility Classes that can be implemented into your own Classes to ease the execution of many common tasks.

	license: MIT-style license.

	requires: Class

	provides: [Class.Extras, Chain, Events, Options]

	...
	*/

	(function () {

		// #region Chain

		/**
		* A Utility Class which executes functions one after another, with each function firing after completion of the previous. 
		* Its methods can be implemented with Class:implement into any Class, and it is currently implemented in Fx and Request. 
		* In Fx, for example, it is used to create custom, complex animations.
		* 提供链式执行一组函数的工具类. 该类中的方法可以通过Class:implement来实现到其他的Class中.
		* 在本框架中,已实现该工具类的类有Fx和Request. 比如在Fx中,它被用来实现自定义的复杂动画特效
		**/

		this.Chain = new Class({

			$chain: [],

			// Adds functions to the end of the call stack of the Chain instance.
			// 向调用链末端添加新的被调函数
			chain: function () {
				this.$chain.append(Array.flatten(arguments));
				return this;
			},

			// Removes the first function of the Chain instance stack and executes it. The next function will then become first in the array.
			// 执行并删除调用链顶端的一个被调函数(原先调用链上第二位函数将提升为第一位)
			callChain: function () {
				return (this.$chain.length) ? this.$chain.shift().apply(this, arguments) : false;
			},

			// Clears the stack of a Chain instance
			// 清空调用链
			clearChain: function () {
				this.$chain.empty();
				return this;
			}

		});

		// #endregion Chain

		// #region Events

		/**
		* A Utility Class. Its methods can be implemented with Class:implement into any Class. In Fx, for example, 
		* this Class is used to allow any number of functions to be added to the Fx events, like 'complete', 'start', and 'cancel'. 
		* Events in a Class that implements Events must be either added as an option or with addEvent, not directly through .options.onEventName.
		*
		* 事件相关的工具类. 该类中的方法可以通过Class:implement实现到其他的Class中.
		* 比如在Fx类中, 它被用于提供向Fx中添加任意多个事件的能力, 如: 'complete', 'start', 以及 'cancel'.
		* 实现Events的类必须通过使用option的方式或调用addEvent方法来添加事件, 不能直接通过 .options.onEventName 的方式来进行.
		**/

		var removeOn = function (string) {
			return string.replace(/^on([A-Z])/, function (full, first) {
				return first.toLowerCase();
			});
		};

		this.Events = new Class({

			$events: {},

			// Adds an event to the Class instance's event stack
			// 向类实例的事件栈中添加一个事件
			addEvent: function (type, fn, internal) {
				type = removeOn(type);

				this.$events[type] = (this.$events[type] || []).include(fn);
				if (internal) { fn.internal = true; }
				return this;
			},

			// The same as addEvent, but accepts an object to add multiple events at once
			// 和addEvent功能类似, 区别之处在于可一次添加多个事件
			addEvents: function (events) {
				for (var type in events) {
					this.addEvent(type, events[type]);
				}
				return this;
			},

			// Fires all events of the specified type in the Class instance.
			// 触发指定事件类型的下所有监听函数
			fireEvent: function (type, args, delay) {
				type = removeOn(type);
				var events = this.$events[type];
				if (!events) { return this; }
				args = Array.from(args);
				events.each(function (fn) {
					if (delay) {
						fn.delay(delay, this, args);
					} else {
						fn.apply(this, args);
					}
				}, this);
				return this;
			},

			// Removes an event from the stack of events of the Class instance
			// 删除指定类型事件下的指定监听函数
			removeEvent: function (type, fn) {
				type = removeOn(type);
				var events = this.$events[type];
				if (events && !fn.internal) {
					var index = events.indexOf(fn);
					if (index != -1) { delete events[index]; }
				}
				return this;
			},

			// Removes all events of the given type from the stack of events of a Class instance. If no type is specified, removes all events of all types
			// 删除指定类型事件下的所有监听函数. 如果未指定事件类型,则删除全部类型下的所有监听函数
			removeEvents: function (events) {
				var type;
				if (typeOf(events) == 'object') {
					for (type in events) {
						this.removeEvent(type, events[type]);
					}
					return this;
				}
				if (events) { events = removeOn(events); }
				for (type in this.$events) {
					if (events && events != type) { continue; }
					var fns = this.$events[type];
					for (var i = fns.length; i--; ) {
						if (i in fns) {
							this.removeEvent(type, fns[i]);
						}
					}
				}
				return this;
			}

		});

		// #endregion Events

		// #region Options

		/**
		* A Utility Class. Its methods can be implemented with Class:implement into any Class. Used to automate the setting of a Class instance's options. 
		* Will also add Class Events when the option property begins with 'on' and is followed by a capital letter (e.g. 'onComplete' adds a 'complete' event). 
		* You will need to call this.setOptions() for this to have an effect, however
		* 
		* 可选项配置相关的工具类. 该类中的方法可以通过Class:implement实现到其他的Class中.
		* 用于提供自动化设置类实例的可选项.
		* 和Events类协作时,当可选项属性名以'on'开头并且紧接大写字母开头的单词时,这个属性将被认为是一个事件而自动进行处理(例如: 'onComplete'将被处理为'complete'事件)
		**/

		this.Options = new Class({

			setOptions: function () {
				var options = this.options = Object.merge.apply(null, [{}, this.options].append(arguments));
				if (this.addEvent) {
					for (var option in options) {
						if (typeOf(options[option]) != 'function' || !(/^on[A-Z]/).test(option)) {
							continue;
						}
						this.addEvent(option, options[option]);
						delete options[option];
					}
				}
				return this;
			}

		});

		// #endregion Options

	})();

	// #endregion

	// #region - Class.refactor -

	/*
	---

	script: Class.Refactor.js

	name: Class.Refactor

	description: Extends a class onto itself with new property, preserving any items attached to the class's namespace.

	license: MIT-style license

	authors:
	- Aaron Newton

	requires:
	- Core/Class
	- /MooTools.More

	# Some modules declare themselves dependent on Class.Refactor
	provides: [Class.refactor, Class.Refactor]

	...
	*/

	Class.refactor = function (original, refactors) {

		Object.each(refactors, function (item, name) {
			var origin = original.prototype[name];
			origin = (origin && origin.$origin) || origin || function () { };
			original.implement(name, (typeof item == 'function') ? function () {
				var old = this.previous;
				this.previous = origin;
				var value = item.apply(this, arguments);
				this.previous = old;
				return value;
			} : item);
		});

		return original;

	};

	// #endregion

	// #region - Class.Binds -

	/*
	---

	script: Class.Binds.js

	name: Class.Binds

	description: Automagically binds specified methods in a class to the instance of the class.

	license: MIT-style license

	authors:
	- Aaron Newton

	requires:
	- Core/Class
	- /MooTools.More

	provides: [Class.Binds]

	...
	*/

	Class.Mutators.Binds = function (binds) {
		// 如果传送给新类的构造函数的对象中没有定义initialize方法，则为新类定义一个空的initialize方法。
		if (!this.prototype.initialize) {
			this.implement('initialize', function () { });
		}
		// 把定义的Binds键值与类中已定义的Binds(继承自父类)属性值合并为一个数组
		return Array.from(binds).concat(this.prototype.Binds || []);
	};

	// 绝妙的构思，把initialize定义为一个Mutator，这里传递过来的参数就是类构造函数中的initialize(初始化)方法
	Class.Mutators.initialize = function (initialize) {
		// 返回闭包作为类的initialize方法
		return function () {
			// 绑定Binds属性中包含的每个方法的作用域，替代原方法
			Array.from(this.Binds).each(function (name) {
				var original = this[name];
				if (original) { this[name] = original.bind(this); }
			}, this);
			// 执行类设计时构造函数中定义的initialize方法
			return initialize.apply(this, arguments);
		};
	};

	// #endregion

	// #endregion

	// #region -- JSON --

	/*
	---

	name: JSON

	description: JSON encoder and decoder.

	license: MIT-style license.

	See Also: <http://www.json.org/>

	requires: [Array, String, Number, Function]

	provides: JSON

	...
	*/

	if (typeof JSON == 'undefined') { this.JSON = {}; }

	(function () {

		var special = { '\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"': '\\"', '\\': '\\\\' };

		var escape = function (chr) {
			return special[chr] || '\\u' + ('0000' + chr.charCodeAt(0).toString(16)).slice(-4);
		};

		JSON.validate = function (string) {
			string = string.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
					replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
					replace(/(?:^|:|,)(?:\s*\[)+/g, '');

			return (/^[\],:{}\s]*$/).test(string);
		};

		JSON.encode = JSON.stringify ? function (obj) {
			return JSON.stringify(obj);
		} : function (obj) {
			if (obj && obj.toJSON) { obj = obj.toJSON(); }

			switch (typeOf(obj)) {
				case 'string':
					return '"' + obj.replace(/[\x00-\x1f\\"]/g, escape) + '"';

				case 'array':
					return '[' + obj.map(JSON.encode).clean() + ']';

				case 'object': case 'hash':
					var string = [];
					Object.each(obj, function (value, key) {
						var json = JSON.encode(value);
						if (json) string.push(JSON.encode(key) + ':' + json);
					});
					return '{' + string + '}';

				case 'number': case 'boolean': return '' + obj;

				case 'null': return 'null';
			}

			return null;
		};

		JSON.decode = function (string, secure) {
			if (!string || typeOf(string) != 'string') { return null; }

			if (secure || JSON.secure) {
				if (JSON.parse) { return JSON.parse(string); }
				if (!JSON.validate(string)) {
					throw new Error('JSON could not decode the input; security is enabled and the value is not secure.');
				}
			}

			return eval('(' + string + ')');
		};

	})();

	// #endregion

	// #region -- Cookie --

	/*
	---

	name: Cookie

	description: Class for creating, reading, and deleting browser Cookies.

	license: MIT-style license.

	credits:
	- Based on the functions by Peter-Paul Koch (http://quirksmode.org).

	requires: [Options, Browser]

	provides: Cookie

	...
	*/

	var Cookie = this.Cookie = new Class({

		Implements: Options,

		options: {
			path: '/',
			domain: false,
			duration: false,
			secure: false,
			document: document,
			encode: true
		},

		initialize: function (key, options) {
			this.key = key;
			this.setOptions(options);
		},

		write: function (value) {
			if (this.options.encode) {
				value = encodeURIComponent(value);
			}
			if (this.options.domain) {
				value += '; domain=' + this.options.domain;
			}
			if (this.options.path) {
				value += '; path=' + this.options.path;
			}
			if (this.options.duration) {
				var date = new Date();
				date.setTime(date.getTime() + this.options.duration * 24 * 60 * 60 * 1000);
				value += '; expires=' + date.toGMTString();
			}
			if (this.options.secure) {
				value += '; secure';
			}
			this.options.document.cookie = this.key + '=' + value;
			return this;
		},

		read: function () {
			var value = this.options.document.cookie.match('(?:^|;)\\s*' + this.key.escapeRegExp() + '=([^;]*)');
			return (value) ? decodeURIComponent(value[1]) : null;
		},

		dispose: function () {
			new Cookie(this.key, Object.merge({}, this.options, { duration: -1 })).write('');
			return this;
		}

	});

	Cookie.write = function (key, value, options) {
		return new Cookie(key, options).write(value);
	};

	Cookie.read = function (key) {
		return new Cookie(key).read();
	};

	Cookie.dispose = function (key, options) {
		return new Cookie(key, options).dispose();
	};

	// #endregion

	// #region -- Locale --

	/*
	* name: Locale
	* 
	* description: Provides methods for localization.
	* 
	* authors:
	*		- Aaron Newton
	*		- Arian Stolwijk
	* 
	* requires:
	*		- Core/Events
	*		- /Object.Extras
	*		- /MooTools.More
	* 
	* provides: [Locale, Lang]
	*/

	(function () {

		var current = null,
				locales = {},
				inherits = {};

		var getSet = function (set) {
			if (instanceOf(set, Locale.Set)) {
				return set;
			} else {
				return locales[set];
			}
		};

		var Locale = this.Locale = {

			define: function (locale, set, key, value) {
				var name;
				if (instanceOf(locale, Locale.Set)) {
					name = locale.name;
					if (name) { locales[name] = locale; }
				} else {
					name = locale;
					if (!locales[name]) {
						locales[name] = new Locale.Set(name);
					}
					locale = locales[name];
				}

				if (set) { locale.define(set, key, value); }

				if (!current) { current = locale; }

				return locale;
			},

			use: function (locale) {
				locale = getSet(locale);

				if (locale) {
					current = locale;
					this.fireEvent('change', locale);
				}

				return this;
			},

			getCurrent: function () {
				return current;
			},

			get: function (key, args) {
				return (current) ? current.get(key, args) : '';
			},

			inherit: function (locale, inherits, set) {
				locale = getSet(locale);

				if (locale) { locale.inherit(inherits, set); }
				return this;
			},

			list: function () {
				return Object.keys(locales);
			}

		};

		Object.append(Locale, new Events);

		Locale.Set = new Class({

			sets: {},

			inherits: {
				locales: [],
				sets: {}
			},

			initialize: function (name) {
				this.name = name || '';
			},

			define: function (set, key, value) {
				var defineData = this.sets[set];
				if (!defineData) { defineData = {}; }

				if (key) {
					if (typeOf(key) == 'object') {
						defineData = Object.merge(defineData, key);
					} else {
						defineData[key] = value;
					}
				}
				this.sets[set] = defineData;

				return this;
			},

			get: function (key, args, _base) {
				var value = Object.getFromPath(this.sets, key);
				if (value != null) {
					var type = typeOf(value);
					if (type == 'function') {
						value = value.apply(null, Array.from(args));
					} else if (type == 'object') {
						value = Object.clone(value);
					}
					return value;
				}

				// get value of inherited locales
				var index = key.indexOf('.'),
						set = index < 0 ? key : key.substr(0, index),
						names = (this.inherits.sets[set] || []).combine(this.inherits.locales).include('en-US');
				if (!_base) { _base = []; }

				/**
				# 苦苦的苦瓜 
				# 2011-10-12
				# for循环改为while循环
				# for (var i = 0, l = names.length; i < l; i++) {
				**/
				var i = 0, l = names.length;
				while (i < l) {
					var $_name = names[i++];
					if (_base.contains($_name)) { continue; }
					_base.include($_name);

					var locale = locales[$_name];
					if (!locale) { continue; }

					value = locale.get(key, args, _base);
					if (value != null) { return value; }
				}

				return '';
			},

			inherit: function (names, set) {
				names = Array.from(names);

				if (set && !this.inherits.sets[set]) {
					this.inherits.sets[set] = [];
				}

				var l = names.length;
				while (l--) {
					(set ? this.inherits.sets[set] : this.inherits.locales).unshift(names[l]);
				}

				return this;
			}

		});

	})();

	// #endregion Locale

	// #region -- Locale.Set.From --

	/**
	* name: Locale.Set.From
	* 
	* description: Provides an alternative way to create Locale.Set objects.
	* 
	* authors:
	*		- Tim Wienk
	* 
	* requires:
	*		- Core/JSON
	*		- /Locale
	* 
	* provides: Locale.Set.From
	**/

	(function () {

		var parsers = {
			'json': JSON.decode
		};

		Locale.Set.defineParser = function (name, fn) {
			parsers[name] = fn;
		};

		Locale.Set.from = function (set, type) {
			if (instanceOf(set, Locale.Set)) { return set; }

			if (!type && typeOf(set) == 'string') { type = 'json'; }
			if (parsers[type]) { set = parsers[type](set); }

			var locale = new Locale.Set;

			locale.sets = set.sets || {};

			if (set.inherits) {
				locale.inherits.locales = Array.from(set.inherits.locales);
				locale.inherits.sets = set.inherits.sets || {};
			}

			return locale;
		};

	})();

	// #endregion Locale.Set.From

});